phpmyadmin (#66)

* add phpmyadmin

* add tests
This commit is contained in:
Saeed Vaziry 2023-10-10 17:15:58 +02:00 committed by GitHub
parent 7c5505be16
commit 4bd4b34d24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 230 additions and 30 deletions

View File

@ -1,7 +1,8 @@
<?php <?php
namespace App\Actions\Database; namespace App\Actions\Service;
use App\Enums\ServiceStatus;
use App\Models\Server; use App\Models\Server;
use App\Models\Service; use App\Models\Service;
use Illuminate\Support\Facades\Validator; use Illuminate\Support\Facades\Validator;
@ -18,23 +19,21 @@ public function install(Server $server, array $input): Service
$phpMyAdmin = $server->defaultService('phpmyadmin'); $phpMyAdmin = $server->defaultService('phpmyadmin');
if ($phpMyAdmin) { if ($phpMyAdmin) {
if ($phpMyAdmin->status === 'ready') { throw ValidationException::withMessages([
throw ValidationException::withMessages([ 'allowed_ip' => __('Already installed'),
'install' => __('Already installed'), ]);
])->errorBag('installPHPMyAdmin');
}
$phpMyAdmin->delete();
} }
$phpMyAdmin = new Service([ $phpMyAdmin = new Service([
'server_id' => $server->id, 'server_id' => $server->id,
'type' => 'phpmyadmin', 'type' => 'phpmyadmin',
'type_data' => [ 'type_data' => [
'allowed_ip' => $input['allowed_ip'], 'allowed_ip' => $input['allowed_ip'],
'port' => $input['port'],
'php' => $server->defaultService('php')->version, 'php' => $server->defaultService('php')->version,
], ],
'name' => 'phpmyadmin', 'name' => 'phpmyadmin',
'version' => '5.1.2', 'version' => '5.1.2',
'status' => 'installing', 'status' => ServiceStatus::INSTALLING,
'is_default' => 1, 'is_default' => 1,
]); ]);
$phpMyAdmin->save(); $phpMyAdmin->save();
@ -50,6 +49,12 @@ private function validate(array $input): void
{ {
Validator::make($input, [ Validator::make($input, [
'allowed_ip' => 'required', 'allowed_ip' => 'required',
])->validateWithBag('installPHPMyAdmin'); 'port' => [
'required',
'numeric',
'min:1',
'max:65535',
],
])->validate();
} }
} }

View File

@ -0,0 +1,31 @@
<?php
namespace App\Http\Livewire\Services;
use App\Actions\Service\InstallPHPMyAdmin as InstallPHPMyAdminAction;
use App\Models\Server;
use Illuminate\Contracts\View\View;
use Livewire\Component;
class InstallPHPMyAdmin extends Component
{
public Server $server;
public string $allowed_ip;
public string $port = '5433';
public function install(): void
{
app(InstallPHPMyAdminAction::class)->install($this->server, $this->all());
$this->dispatchBrowserEvent('started', true);
$this->emitTo(ServicesList::class, '$refresh');
}
public function render(): View
{
return view('livewire.services.install-phpmyadmin');
}
}

View File

@ -3,6 +3,7 @@
namespace App\Http\Livewire\Services; namespace App\Http\Livewire\Services;
use App\Models\Server; use App\Models\Server;
use App\Models\Service;
use App\Traits\RefreshComponentOnBroadcast; use App\Traits\RefreshComponentOnBroadcast;
use Illuminate\Contracts\View\View; use Illuminate\Contracts\View\View;
use Livewire\Component; use Livewire\Component;
@ -15,6 +16,7 @@ class ServicesList extends Component
public function stop(int $id): void public function stop(int $id): void
{ {
/** @var Service $service */
$service = $this->server->services()->where('id', $id)->firstOrFail(); $service = $this->server->services()->where('id', $id)->firstOrFail();
$service->stop(); $service->stop();
@ -24,6 +26,7 @@ public function stop(int $id): void
public function start(int $id): void public function start(int $id): void
{ {
/** @var Service $service */
$service = $this->server->services()->where('id', $id)->firstOrFail(); $service = $this->server->services()->where('id', $id)->firstOrFail();
$service->start(); $service->start();
@ -33,6 +36,7 @@ public function start(int $id): void
public function restart(int $id): void public function restart(int $id): void
{ {
/** @var Service $service */
$service = $this->server->services()->where('id', $id)->firstOrFail(); $service = $this->server->services()->where('id', $id)->firstOrFail();
$service->restart(); $service->restart();
@ -40,6 +44,16 @@ public function restart(int $id): void
$this->refreshComponent([]); $this->refreshComponent([]);
} }
public function uninstall(int $id): void
{
/** @var Service $service */
$service = $this->server->services()->where('id', $id)->firstOrFail();
$service->uninstall();
$this->refreshComponent([]);
}
public function render(): View public function render(): View
{ {
return view('livewire.services.services-list', [ return view('livewire.services.services-list', [

View File

@ -3,6 +3,7 @@
namespace App\Jobs\Installation; namespace App\Jobs\Installation;
use App\Actions\FirewallRule\CreateRule; use App\Actions\FirewallRule\CreateRule;
use App\Enums\ServiceStatus;
use App\Jobs\Job; use App\Jobs\Job;
use App\Models\FirewallRule; use App\Models\FirewallRule;
use App\Models\Service; use App\Models\Service;
@ -32,6 +33,9 @@ public function handle(): void
$this->downloadSource(); $this->downloadSource();
$this->setUpVHost(); $this->setUpVHost();
$this->restartPHP(); $this->restartPHP();
$this->service->update([
'status' => ServiceStatus::READY,
]);
} }
/** /**
@ -41,7 +45,7 @@ private function setUpFirewall(): void
{ {
$this->firewallRule = FirewallRule::query() $this->firewallRule = FirewallRule::query()
->where('server_id', $this->service->server_id) ->where('server_id', $this->service->server_id)
->where('port', '54331') ->where('port', $this->service->type_data['port'])
->first(); ->first();
if ($this->firewallRule) { if ($this->firewallRule) {
$this->firewallRule->source = $this->service->type_data['allowed_ip']; $this->firewallRule->source = $this->service->type_data['allowed_ip'];
@ -52,7 +56,7 @@ private function setUpFirewall(): void
[ [
'type' => 'allow', 'type' => 'allow',
'protocol' => 'tcp', 'protocol' => 'tcp',
'port' => '54331', 'port' => $this->service->type_data['port'],
'source' => $this->service->type_data['allowed_ip'], 'source' => $this->service->type_data['allowed_ip'],
'mask' => '0', 'mask' => '0',
] ]
@ -78,6 +82,7 @@ private function setUpVHost(): void
{ {
$vhost = File::get(resource_path('commands/webserver/nginx/phpmyadmin-vhost.conf')); $vhost = File::get(resource_path('commands/webserver/nginx/phpmyadmin-vhost.conf'));
$vhost = Str::replace('__php_version__', $this->service->server->defaultService('php')->version, $vhost); $vhost = Str::replace('__php_version__', $this->service->server->defaultService('php')->version, $vhost);
$vhost = Str::replace('__port__', $this->service->type_data['port'], $vhost);
$this->service->server->ssh()->exec( $this->service->server->ssh()->exec(
new CreateNginxPHPMyAdminVHostCommand($vhost), new CreateNginxPHPMyAdminVHostCommand($vhost),
'create-phpmyadmin-vhost' 'create-phpmyadmin-vhost'
@ -98,6 +103,9 @@ private function restartPHP(): void
public function failed(Throwable $throwable): Throwable public function failed(Throwable $throwable): Throwable
{ {
$this->firewallRule?->removeFromServer(); $this->firewallRule?->removeFromServer();
$this->service->update([
'status' => ServiceStatus::INSTALLATION_FAILED,
]);
throw $throwable; throw $throwable;
} }
} }

View File

@ -37,7 +37,7 @@ private function removeFirewallRule(): void
/** @var ?FirewallRule $rule */ /** @var ?FirewallRule $rule */
$rule = FirewallRule::query() $rule = FirewallRule::query()
->where('server_id', $this->service->server_id) ->where('server_id', $this->service->server_id)
->where('port', '54331') ->where('port', $this->service->type_data['port'])
->first(); ->first();
$rule?->removeFromServer(); $rule?->removeFromServer();
} }

View File

@ -76,7 +76,7 @@ public function uninstaller(): mixed
return new $uninstaller($this); return new $uninstaller($this);
} }
public function getUnitAttribute($value): string public function getUnitAttribute($value): ?string
{ {
if ($value) { if ($value) {
return $value; return $value;

View File

@ -324,7 +324,6 @@
'https' => 443, 'https' => 443,
'mysql' => 3306, 'mysql' => 3306,
'ftp' => 21, 'ftp' => 21,
'phpmyadmin' => 54331,
'tcp' => '', 'tcp' => '',
'udp' => '', 'udp' => '',
], ],

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="3890" height="2168" id="svg2">
<metadata id="metadata8">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
<dc:title/>
</cc:Work>
</rdf:RDF>
</metadata>
<defs id="defs6"/>
<g id="g5" style="fill:#cccccc">
<path d="m 2889.39,6.3480122 -2.04,-4.07 c -1.01,-1.01 -2.03,-2.04 -4.06,-2.04 l -4.08,1.03 c -2.03,2.03 -3.05,3.05 -3.05,5.08 L 2789.64,1572.695 l 13.24,-2.035 83.46,-1523.70199 99.75,163.88 -1.02,0 c 75.32,221.88 106.87,458.02 94.66,708.41003 l 6.11,9.16 98.73,175.05996 6.1,6.11 c 151.66,133.336 321.63,222.907 509.94,268.707 l 45.8,74.309 6.11,2.031 1.02,-2.031 -866.19,-1416.82599 2.04,-29.52" id="path14"/>
<path d="m 2858.86,559.02801 c 106.87,218.84 145.54,549.62999 117.05,992.39199 l 416.29,-50.894 z" id="path18"/>
<path d="m 3807.48,1520.881 c 42.74,-5.086 70.22,-14.246 82.44,-27.476 l -2178.16,265.656 -1.02,0 c 1.02,90.586 41.73,161.836 121.12,212.723 21.37,15.269 43.77,26.465 64.12,33.59 19.34,-22.387 40.72,-38.676 66.17,-53.946 l 1.01,0 c 228,-138.422 566.94,-159.8 1014.78,-65.136 l 5.09,1.011 c 48.86,10.18 97.71,22.399 143.52,36.645 13.22,2.035 24.42,-2.035 33.58,-10.18 16.29,-12.215 36.65,-21.375 64.13,-27.476 l 0,-1.02 c 72.27,-128.25 169.97,-222.906 292.12,-284.996 84.48,-41.727 182.19,-69.215 291.1,-79.395" id="path20"/>
<path d="M 2761.15,1560.585 2860.89,31.798012 C 2716.36,589.56801 2484.29,1110.698 2165.71,1594.167 l 595.44,-33.582" id="path22"/>
<path d="m 2200.32,329.008 -4.07,-2.04 -4.07,1.02 -2.04,5.08 -82.44,1323.18799 12.21,-1.019 82.45,-1322.169 -2.04,-4.06" id="path24"/>
<path d="m 2084.29,1627.756 0,0 87.53,-1290.608 -461.08,1330.308 373.55,-39.7" id="path26"/>
</g>
<g id="g13" style="fill:none;stroke:#cccccc;stroke-width:12;stroke-linecap:round;stroke-linejoin:round">
<path d="m 2102.61,2057.9534 c -115.02,54.9606 -198.48,64.1207 -251.41,30.5387 -52.93,-35.6247 -134.36,-27.4847 -244.28,24.4219" id="path34"/>
<path d="m 2372.33,2066.093 c -21.37,-7.125 -44.78,-12.211 -69.21,-14.25 -49.87,-4.066 -109.93,15.27 -180.16,57.0042 -70.23,42.746 -154.71,59.0351 -255.48,49.8711" id="path36"/>
<path d="m 3000.34,1962.273 c -484.5,-99.742 -833.61,-76.336 -1047.35,71.25" id="path38"/>
<path d="m 3305.69,2010.117 c -21.38,-8.145 -44.79,-13.235 -69.22,-14.254 -49.87,-4.067 -109.92,15.269 -180.15,57.004 -70.23,41.7262 -154.71,58.0114 -255.48,49.8708" id="path40"/>
<path d="m 2655.29,341.21801 c -49.88,-30.54 -101.78,-22.39 -155.73,25.44 -46.82,-47.83 -95.67,-55.98 -146.57,-25.44" id="path42" style="stroke-width:29"/>
<path d="m 2542.31,170.21801 c -50.89,-30.53 -100.76,-18.32 -151.66,36.64 -49.88,-54.96 -100.76,-67.17 -151.66,-36.64" id="path44" style="stroke-width:29"/>
</g>
<g style="fill:#6c78af" id="g33">
<path d="m 56.770404,1763.8603 134.914516,0 c 40.53785,0 70.3051,11.5406 89.30315,34.6149 18.99058,23.0812 25.15303,55.2422 18.48477,96.4878 -2.73388,16.9207 -7.61168,32.4501 -14.63698,46.5933 -7.02825,14.1442 -16.30891,27.067 -27.84598,38.7573 -13.71822,14.0684 -29.07355,24.148 -46.07783,30.2307 -17.00335,6.0818 -38.74881,9.1232 -65.23042,9.1232 l -60.093245,0 -14.951878,92.5154 -70.16450702,0 56.29840402,-348.3226 z m 61.252276,55.1047 -23.613063,146.1033 42.675303,0 c 28.28742,0 49.25184,-5.7744 62.90101,-17.3383 13.63797,-11.5649 22.6337,-30.807 26.98842,-57.7355 4.19709,-25.968 1.75658,-44.2941 -7.2996,-54.9935 -9.06329,-10.6883 -26.92099,-16.036 -53.57751,-16.036 l -48.07456,0" id="path66"/>
<path d="m 378.24196,1671.3451 69.63516,0 -14.95189,92.5152 61.94982,0 c 38.98987,0 66.01185,7.3901 81.07593,22.1571 15.06891,14.7762 19.95224,38.5804 14.64264,71.4329 l -26.22037,162.2172 -70.68973,0 24.9538,-154.3893 c 2.84147,-17.5516 1.46456,-29.4876 -4.12427,-35.815 -5.58913,-6.3193 -17.28356,-9.4871 -35.06873,-9.4871 l -55.57891,0 -32.27423,199.6914 -69.64729,0 56.29807,-348.3224" id="path68"/>
<path d="m 666.43774,1763.8603 134.9135,0 c 40.54695,0 70.30511,11.5406 89.30319,34.6149 18.99454,23.0812 25.15404,55.2422 18.4898,96.4878 -2.7339,16.9207 -7.61577,32.4501 -14.63297,46.5933 -7.03329,14.1442 -16.32202,27.067 -27.85103,38.7573 -13.72229,14.0684 -29.07657,24.148 -46.08084,30.2307 -17.00032,6.0818 -38.74478,9.1232 -65.23548,9.1232 l -60.08435,0 -14.95188,92.5154 -70.16093,0 56.29099,-348.3226 z m 61.26036,55.1047 -23.61306,146.1033 42.6753,0 c 28.28641,0 49.2478,-5.7744 62.88888,-17.3383 13.641,-11.5649 22.64179,-30.807 26.99549,-57.7355 4.19406,-25.968 1.7576,-44.2941 -7.30364,-54.9935 -9.06329,-10.6883 -26.92099,-16.036 -53.56841,-16.036 l -48.07456,0" id="path70"/>
</g>
<g style="fill:#f89c0e" id="g65">
<path d="m 1027.7488,1597.3243 134.9473,0 59.2813,323.8687 163.9729,-323.8687 134.4328,0 -68.203,422.055 -90.0955,0 60.5624,-328.7447 -165.335,328.7447 -97.63,0 -62.0922,-332.1897 -44.4691,332.1897 -93.58345,0 68.21155,-422.055" id="path72"/>
<path d="m 1682.3349,1951.0787 68.129,0 39.0484,-241.6556 84.6928,0 -48.7474,301.634 c -6.6176,41.0085 -21.4426,71.3829 -44.4508,91.1237 -23.0089,19.7312 -54.9295,29.6038 -95.7507,29.6038 l -166.0776,0 10.1515,-62.7878 151.4988,0 c 16.2574,0 29.3646,-3.7991 39.3223,-11.39 9.9443,-7.6043 16.0994,-18.6108 18.427,-33.0342 l 0.8443,-5.1933 -74.9653,0 c -47.9513,0 -80.6531,-9.1406 -98.0934,-27.4219 -17.4525,-18.2801 -22.7167,-48.7649 -15.8297,-91.453 l 30.891,-191.0813 83.7372,0 -29.8633,184.7645 c -3.7745,23.3729 -2.642,38.6968 3.4343,45.9753 6.0641,7.2784 20.5937,10.9158 43.6016,10.9158" id="path74"/>
<path d="m 2102.3044,1597.3243 97.5197,0 118.1874,422.055 -102.2734,0 -23.907,-100.4601 -189.9554,0 -55.1868,100.4601 -97.5321,0 253.1476,-422.055 z m 31.6507,83.8058 -90.1808,162.444 130.2183,0 -40.0375,-162.444" id="path76"/>
<path d="m 2637.3031,2019.3793 -162.6964,0 c -49.1642,0 -85.2663,-13.9786 -108.3193,-41.9409 -23.0404,-27.9573 -30.5053,-66.9321 -22.4309,-116.9135 3.316,-20.4913 9.2287,-39.3092 17.7509,-56.4463 8.5217,-17.1419 19.771,-32.7965 33.7592,-46.9712 16.6286,-17.0415 35.3095,-29.2498 56.0305,-36.6239 20.7209,-7.3752 47.0449,-11.0604 78.9594,-11.0604 l 72.6621,0 18.1132,-112.0988 84.3865,0 -68.2152,422.055 z m -73.6376,-66.4629 28.5697,-176.7241 -51.2224,0 c -34.3524,0 -59.8397,6.9489 -76.4874,20.8321 -16.6223,13.8929 -27.5723,37.0269 -32.8017,69.397 -5.0795,31.4221 -2.0777,53.6898 9.0062,66.8122 11.0837,13.1222 32.7053,19.6828 64.8648,19.6828 l 58.0708,0" id="path78"/>
<path d="m 2761.0228,1709.4231 325.2334,0 c 47.155,0 79.7016,8.9067 97.6259,26.6992 17.9129,17.8022 23.6511,46.7028 17.1903,86.702 l -31.7718,196.555 -85.3299,0 30.0434,-185.9259 c 3.6903,-22.7947 2.5585,-37.8305 -3.3836,-45.1151 -5.966,-7.2785 -20.0182,-10.9208 -42.1807,-10.9208 l -47.5103,0 -39.1073,241.9618 -86.604,0 39.1073,-241.9618 -98.9777,0 -39.1073,241.9618 -85.3298,0 50.1021,-309.9562" id="path80"/>
<path d="m 3389.6515,1674.2008 -88.8214,0 12.4228,-76.8765 88.8214,0 -12.4228,76.8765 z m -55.7924,345.1785 -88.8215,0 50.0899,-309.9562 88.8214,0 -50.0898,309.9562" id="path82"/>
<path d="m 3457.2112,1709.4231 159.3518,0 c 48.1596,0 81.1348,8.7634 98.9115,26.2691 17.7775,17.5156 23.3935,46.5596 16.8359,87.1321 l -31.7597,196.555 -84.705,0 30.1524,-186.5005 c 3.7421,-23.1817 2.4511,-38.2189 -3.8732,-45.1102 -6.325,-6.9 -20.6913,-10.3511 -43.0866,-10.3511 l -68.1168,0 -39.1072,241.9618 -84.6928,0 50.0897,-309.9562" id="path84"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.6 KiB

View File

@ -1,5 +1,5 @@
server { server {
listen 54331; listen __port__;
server_name _; server_name _;
root /home/vito/phpmyadmin; root /home/vito/phpmyadmin;

View File

@ -0,0 +1,33 @@
<x-modal name="install-phpmyadmin">
<form wire:submit.prevent="install" class="p-6">
<h2 class="text-lg font-medium text-gray-900 dark:text-gray-100">
{{ __('Install PHPMyAdmin') }}
</h2>
<div class="mt-6">
<x-input-label for="allowed_ip" :value="__('Allowed IP')" />
<x-text-input wire:model.defer="allowed_ip" id="allowed_ip" name="allowed_ip" class="mt-1 w-full" />
@error('allowed_ip')
<x-input-error class="mt-2" :messages="$message" />
@enderror
</div>
<div class="mt-6">
<x-input-label for="port" :value="__('Port')" />
<x-text-input wire:model.defer="port" id="port" name="port" class="mt-1 w-full" />
@error('port')
<x-input-error class="mt-2" :messages="$message" />
@enderror
</div>
<div class="mt-6 flex justify-end">
<x-secondary-button type="button" x-on:click="$dispatch('close')">
{{ __('Cancel') }}
</x-secondary-button>
<x-primary-button class="ml-3" @started.window="$dispatch('close')">
{{ __('Install') }}
</x-primary-button>
</div>
</form>
</x-modal>

View File

@ -1,11 +1,29 @@
<div> <div>
<x-card-header> <x-card-header>
<x-slot name="title">{{ __("Services") }}</x-slot> <x-slot name="title">{{ __('Services') }}</x-slot>
<x-slot name="description">{{ __("All services that we installed on your server are here") }}</x-slot> <x-slot name="description">{{ __('All services that we installed on your server are here') }}</x-slot>
<x-slot name="aside">
<x-dropdown>
<x-slot name="trigger">
<x-primary-button>
{{ __('Install Service') }}
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-4 h-4 ml-1">
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
</svg>
</x-primary-button>
</x-slot>
<x-slot name="content">
<x-dropdown-link class="cursor-pointer" x-on:click="$dispatch('open-modal', 'install-phpmyadmin')">
{{ __('PHPMyAdmin') }}
</x-dropdown-link>
</x-slot>
</x-dropdown>
<livewire:services.install-p-h-p-my-admin :server="$server" />
</x-slot>
</x-card-header> </x-card-header>
<div class="space-y-3"> <div class="space-y-3">
@foreach($services as $service) @foreach ($services as $service)
<x-item-card> <x-item-card>
<div class="flex-none"> <div class="flex-none">
<img src="{{ asset('static/images/' . $service->name . '.svg') }}" class="h-10 w-10" alt=""> <img src="{{ asset('static/images/' . $service->name . '.svg') }}" class="h-10 w-10" alt="">
@ -20,24 +38,30 @@
<x-dropdown> <x-dropdown>
<x-slot name="trigger"> <x-slot name="trigger">
<x-secondary-button> <x-secondary-button>
{{ __("Actions") }} {{ __('Actions') }}
</x-secondary-button> </x-secondary-button>
</x-slot> </x-slot>
<x-slot name="content"> <x-slot name="content">
@if($service->status == \App\Enums\ServiceStatus::STOPPED) @if($service->unit)
<x-dropdown-link class="cursor-pointer" wire:click="start({{ $service->id }})"> @if ($service->status == \App\Enums\ServiceStatus::STOPPED)
{{ __("Start") }} <x-dropdown-link class="cursor-pointer" wire:click="start({{ $service->id }})">
{{ __('Start') }}
</x-dropdown-link>
@endif
@if ($service->status == \App\Enums\ServiceStatus::READY)
<x-dropdown-link class="cursor-pointer" wire:click="stop({{ $service->id }})">
{{ __('Stop') }}
</x-dropdown-link>
@endif
<x-dropdown-link class="cursor-pointer" wire:click="restart({{ $service->id }})">
{{ __('Restart') }}
</x-dropdown-link>
@else
<x-dropdown-link class="cursor-pointer" wire:click="uninstall({{ $service->id }})">
{{ __('Uninstall') }}
</x-dropdown-link> </x-dropdown-link>
@endif @endif
@if($service->status == \App\Enums\ServiceStatus::READY)
<x-dropdown-link class="cursor-pointer" wire:click="stop({{ $service->id }})">
{{ __("Stop") }}
</x-dropdown-link>
@endif
<x-dropdown-link class="cursor-pointer" wire:click="restart({{ $service->id }})">
{{ __("Restart") }}
</x-dropdown-link>
</x-slot> </x-slot>
</x-dropdown> </x-dropdown>
</div> </div>

View File

@ -3,8 +3,12 @@
namespace Tests\Feature\Http; namespace Tests\Feature\Http;
use App\Enums\ServiceStatus; use App\Enums\ServiceStatus;
use App\Http\Livewire\Services\InstallPHPMyAdmin;
use App\Http\Livewire\Services\ServicesList; use App\Http\Livewire\Services\ServicesList;
use App\Jobs\Installation\InstallPHPMyAdmin as InstallationInstallPHPMyAdmin;
use App\Jobs\Installation\UninstallPHPMyAdmin;
use App\Jobs\Service\Manage; use App\Jobs\Service\Manage;
use App\Models\Service;
use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Bus; use Illuminate\Support\Facades\Bus;
use Livewire\Livewire; use Livewire\Livewire;
@ -80,6 +84,45 @@ public function test_start_service(string $name): void
Bus::assertDispatched(Manage::class); Bus::assertDispatched(Manage::class);
} }
public function test_install_phpmyadmin(): void
{
Bus::fake();
Livewire::test(InstallPHPMyAdmin::class, ['server' => $this->server])
->set('allowed_ip', '0.0.0.0')
->set('port', 5433)
->call('install')
->assertSuccessful();
Bus::assertDispatched(InstallationInstallPHPMyAdmin::class);
}
public function test_uninstall_phpmyadmin(): void
{
$service = Service::factory()->create([
'server_id' => $this->server->id,
'type' => 'phpmyadmin',
'type_data' => [
'allowed_ip' => '0.0.0.0',
'port' => '5433',
'php' => '8.1',
],
'name' => 'phpmyadmin',
'version' => '5.1.2',
'status' => ServiceStatus::READY,
'is_default' => 1,
]);
Bus::fake();
Livewire::test(ServicesList::class, ['server' => $this->server])
->call('uninstall', $service->id)
->assertSuccessful();
Bus::assertDispatched(UninstallPHPMyAdmin::class);
}
public static function data(): array public static function data(): array
{ {
return [ return [