feat(ca-certificate): add CA certificate management functionality with UI integration and routing
This commit is contained in:
@@ -43,7 +43,7 @@ class Terminal extends Component
|
|||||||
#[On('send-terminal-command')]
|
#[On('send-terminal-command')]
|
||||||
public function sendTerminalCommand($isContainer, $identifier, $serverUuid)
|
public function sendTerminalCommand($isContainer, $identifier, $serverUuid)
|
||||||
{
|
{
|
||||||
$server = Server::ownedByCurrentTeam()->whereUuid($serverUuid)->firstOrFail();
|
$server = Server::ownedByCurrentTeam()->whereUuid($serverUuid)->where('settings.is_terminal_enabled', true)->firstOrFail();
|
||||||
|
|
||||||
if ($isContainer) {
|
if ($isContainer) {
|
||||||
// Validate container identifier format (alphanumeric, dashes, and underscores only)
|
// Validate container identifier format (alphanumeric, dashes, and underscores only)
|
||||||
|
|||||||
@@ -2,12 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Livewire\Server;
|
namespace App\Livewire\Server;
|
||||||
|
|
||||||
use App\Helpers\SslHelper;
|
|
||||||
use App\Jobs\RegenerateSslCertJob;
|
|
||||||
use App\Models\InstanceSettings;
|
use App\Models\InstanceSettings;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\SslCertificate;
|
|
||||||
use Carbon\Carbon;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Hash;
|
use Illuminate\Support\Facades\Hash;
|
||||||
use Livewire\Attributes\Validate;
|
use Livewire\Attributes\Validate;
|
||||||
@@ -17,14 +13,6 @@ class Advanced extends Component
|
|||||||
{
|
{
|
||||||
public Server $server;
|
public Server $server;
|
||||||
|
|
||||||
public ?SslCertificate $caCertificate = null;
|
|
||||||
|
|
||||||
public $showCertificate = false;
|
|
||||||
|
|
||||||
public $certificateContent = '';
|
|
||||||
|
|
||||||
public ?Carbon $certificateValidUntil = null;
|
|
||||||
|
|
||||||
public array $parameters = [];
|
public array $parameters = [];
|
||||||
|
|
||||||
#[Validate(['string'])]
|
#[Validate(['string'])]
|
||||||
@@ -48,27 +36,12 @@ class Advanced extends Component
|
|||||||
$this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail();
|
$this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail();
|
||||||
$this->parameters = get_route_parameters();
|
$this->parameters = get_route_parameters();
|
||||||
$this->syncData();
|
$this->syncData();
|
||||||
$this->loadCaCertificate();
|
|
||||||
} catch (\Throwable) {
|
} catch (\Throwable) {
|
||||||
return redirect()->route('server.index');
|
return redirect()->route('server.index');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function loadCaCertificate()
|
|
||||||
{
|
|
||||||
$this->caCertificate = SslCertificate::where('server_id', $this->server->id)->where('is_ca_certificate', true)->first();
|
|
||||||
|
|
||||||
if ($this->caCertificate) {
|
|
||||||
$this->certificateContent = $this->caCertificate->ssl_certificate;
|
|
||||||
$this->certificateValidUntil = $this->caCertificate->valid_until;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function toggleCertificate()
|
|
||||||
{
|
|
||||||
$this->showCertificate = ! $this->showCertificate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function toggleTerminal($password)
|
public function toggleTerminal($password)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
@@ -100,78 +73,6 @@ class Advanced extends Component
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function saveCaCertificate()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
if (! $this->certificateContent) {
|
|
||||||
throw new \Exception('Certificate content cannot be empty.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! openssl_x509_read($this->certificateContent)) {
|
|
||||||
throw new \Exception('Invalid certificate format.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->caCertificate) {
|
|
||||||
$this->caCertificate->ssl_certificate = $this->certificateContent;
|
|
||||||
$this->caCertificate->save();
|
|
||||||
|
|
||||||
$this->loadCaCertificate();
|
|
||||||
|
|
||||||
$this->writeCertificateToServer();
|
|
||||||
|
|
||||||
dispatch(new RegenerateSslCertJob(
|
|
||||||
server_id: $this->server->id,
|
|
||||||
force_regeneration: true
|
|
||||||
));
|
|
||||||
}
|
|
||||||
$this->dispatch('success', 'CA Certificate saved successfully.');
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
return handleError($e, $this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function regenerateCaCertificate()
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
SslHelper::generateSslCertificate(
|
|
||||||
commonName: 'Coolify CA Certificate',
|
|
||||||
serverId: $this->server->id,
|
|
||||||
isCaCertificate: true,
|
|
||||||
validityDays: 10 * 365
|
|
||||||
);
|
|
||||||
|
|
||||||
$this->loadCaCertificate();
|
|
||||||
|
|
||||||
$this->writeCertificateToServer();
|
|
||||||
|
|
||||||
dispatch(new RegenerateSslCertJob(
|
|
||||||
server_id: $this->server->id,
|
|
||||||
force_regeneration: true
|
|
||||||
));
|
|
||||||
|
|
||||||
$this->loadCaCertificate();
|
|
||||||
$this->dispatch('success', 'CA Certificate regenerated successfully.');
|
|
||||||
} catch (\Throwable $e) {
|
|
||||||
return handleError($e, $this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function writeCertificateToServer()
|
|
||||||
{
|
|
||||||
$caCertPath = config('constants.coolify.base_config_path').'/ssl/';
|
|
||||||
|
|
||||||
$commands = collect([
|
|
||||||
"mkdir -p $caCertPath",
|
|
||||||
"chown -R 9999:root $caCertPath",
|
|
||||||
"chmod -R 700 $caCertPath",
|
|
||||||
"rm -rf $caCertPath/coolify-ca.crt",
|
|
||||||
"echo '{$this->certificateContent}' > $caCertPath/coolify-ca.crt",
|
|
||||||
"chmod 644 $caCertPath/coolify-ca.crt",
|
|
||||||
]);
|
|
||||||
|
|
||||||
remote_process($commands, $this->server);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function syncData(bool $toModel = false)
|
public function syncData(bool $toModel = false)
|
||||||
{
|
{
|
||||||
if ($toModel) {
|
if ($toModel) {
|
||||||
|
|||||||
128
app/Livewire/Server/CaCertificate/Show.php
Normal file
128
app/Livewire/Server/CaCertificate/Show.php
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Livewire\Server\CaCertificate;
|
||||||
|
|
||||||
|
use App\Helpers\SslHelper;
|
||||||
|
use App\Jobs\RegenerateSslCertJob;
|
||||||
|
use App\Models\Server;
|
||||||
|
use App\Models\SslCertificate;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
use Livewire\Attributes\Locked;
|
||||||
|
use Livewire\Component;
|
||||||
|
|
||||||
|
class Show extends Component
|
||||||
|
{
|
||||||
|
#[Locked]
|
||||||
|
public Server $server;
|
||||||
|
|
||||||
|
public ?SslCertificate $caCertificate = null;
|
||||||
|
|
||||||
|
public $showCertificate = false;
|
||||||
|
|
||||||
|
public $certificateContent = '';
|
||||||
|
|
||||||
|
public ?Carbon $certificateValidUntil = null;
|
||||||
|
|
||||||
|
public function mount(string $server_uuid)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$this->server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail();
|
||||||
|
$this->loadCaCertificate();
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return redirect()->route('server.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function loadCaCertificate()
|
||||||
|
{
|
||||||
|
$this->caCertificate = SslCertificate::where('server_id', $this->server->id)->where('is_ca_certificate', true)->first();
|
||||||
|
|
||||||
|
if ($this->caCertificate) {
|
||||||
|
$this->certificateContent = $this->caCertificate->ssl_certificate;
|
||||||
|
$this->certificateValidUntil = $this->caCertificate->valid_until;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function toggleCertificate()
|
||||||
|
{
|
||||||
|
$this->showCertificate = ! $this->showCertificate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saveCaCertificate()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if (! $this->certificateContent) {
|
||||||
|
throw new \Exception('Certificate content cannot be empty.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! openssl_x509_read($this->certificateContent)) {
|
||||||
|
throw new \Exception('Invalid certificate format.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->caCertificate) {
|
||||||
|
$this->caCertificate->ssl_certificate = $this->certificateContent;
|
||||||
|
$this->caCertificate->save();
|
||||||
|
|
||||||
|
$this->loadCaCertificate();
|
||||||
|
|
||||||
|
$this->writeCertificateToServer();
|
||||||
|
|
||||||
|
dispatch(new RegenerateSslCertJob(
|
||||||
|
server_id: $this->server->id,
|
||||||
|
force_regeneration: true
|
||||||
|
));
|
||||||
|
}
|
||||||
|
$this->dispatch('success', 'CA Certificate saved successfully.');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function regenerateCaCertificate()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
SslHelper::generateSslCertificate(
|
||||||
|
commonName: 'Coolify CA Certificate',
|
||||||
|
serverId: $this->server->id,
|
||||||
|
isCaCertificate: true,
|
||||||
|
validityDays: 10 * 365
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->loadCaCertificate();
|
||||||
|
|
||||||
|
$this->writeCertificateToServer();
|
||||||
|
|
||||||
|
dispatch(new RegenerateSslCertJob(
|
||||||
|
server_id: $this->server->id,
|
||||||
|
force_regeneration: true
|
||||||
|
));
|
||||||
|
|
||||||
|
$this->loadCaCertificate();
|
||||||
|
$this->dispatch('success', 'CA Certificate regenerated successfully.');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
return handleError($e, $this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function writeCertificateToServer()
|
||||||
|
{
|
||||||
|
$caCertPath = config('constants.coolify.base_config_path').'/ssl/';
|
||||||
|
|
||||||
|
$commands = collect([
|
||||||
|
"mkdir -p $caCertPath",
|
||||||
|
"chown -R 9999:root $caCertPath",
|
||||||
|
"chmod -R 700 $caCertPath",
|
||||||
|
"rm -rf $caCertPath/coolify-ca.crt",
|
||||||
|
"echo '{$this->certificateContent}' > $caCertPath/coolify-ca.crt",
|
||||||
|
"chmod 644 $caCertPath/coolify-ca.crt",
|
||||||
|
]);
|
||||||
|
|
||||||
|
remote_process($commands, $this->server);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render()
|
||||||
|
{
|
||||||
|
return view('livewire.server.ca-certificate.show');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,9 @@
|
|||||||
<a class="menu-item {{ $activeMenu === 'private-key' ? 'menu-item-active' : '' }}"
|
<a class="menu-item {{ $activeMenu === 'private-key' ? 'menu-item-active' : '' }}"
|
||||||
href="{{ route('server.private-key', ['server_uuid' => $server->uuid]) }}">Private Key
|
href="{{ route('server.private-key', ['server_uuid' => $server->uuid]) }}">Private Key
|
||||||
</a>
|
</a>
|
||||||
|
<a class="menu-item {{ $activeMenu === 'ca-certificate' ? 'menu-item-active' : '' }}"
|
||||||
|
href="{{ route('server.ca-certificate', ['server_uuid' => $server->uuid]) }}">CA Certificate
|
||||||
|
</a>
|
||||||
@if (!$server->isLocalhost())
|
@if (!$server->isLocalhost())
|
||||||
<a class="menu-item {{ $activeMenu === 'cloudflare-tunnels' ? 'menu-item-active' : '' }}"
|
<a class="menu-item {{ $activeMenu === 'cloudflare-tunnels' ? 'menu-item-active' : '' }}"
|
||||||
href="{{ route('server.cloudflare-tunnels', ['server_uuid' => $server->uuid]) }}">Cloudflare
|
href="{{ route('server.cloudflare-tunnels', ['server_uuid' => $server->uuid]) }}">Cloudflare
|
||||||
|
|||||||
@@ -69,7 +69,6 @@
|
|||||||
|
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<h3>Builds</h3>
|
<h3>Builds</h3>
|
||||||
<div>Customize the build process.</div>
|
|
||||||
<div class="flex flex-wrap gap-2 sm:flex-nowrap pt-4">
|
<div class="flex flex-wrap gap-2 sm:flex-nowrap pt-4">
|
||||||
<x-forms.input id="concurrentBuilds" label="Number of concurrent builds" required
|
<x-forms.input id="concurrentBuilds" label="Number of concurrent builds" required
|
||||||
helper="You can specify the number of simultaneous build processes/deployments that should run concurrently." />
|
helper="You can specify the number of simultaneous build processes/deployments that should run concurrently." />
|
||||||
@@ -78,85 +77,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col gap-4 pt-8">
|
|
||||||
<h3>CA SSL Certificate</h3>
|
|
||||||
<div class="flex gap-2">
|
|
||||||
<x-modal-confirmation title="Confirm changing of CA Certificate?" buttonTitle="Save Certificate"
|
|
||||||
submitAction="saveCaCertificate" :actions="[
|
|
||||||
'This will overwrite the existing CA certificate at /data/coolify/ssl/coolify-ca.crt with your custom CA certificate.',
|
|
||||||
'This will regenerate all SSL certificates for databases on this server and it will sign them with your custom CA.',
|
|
||||||
'You must manually redeploy all your databases on this server so that they use the new SSL certificates singned with your new CA certificate.',
|
|
||||||
'Because of caching, you probably also need to redeploy all your resources on this server that are using this CA certificate.',
|
|
||||||
]"
|
|
||||||
confirmationText="/data/coolify/ssl/coolify-ca.crt" shortConfirmationLabel="CA Certificate Path"
|
|
||||||
step3ButtonText="Save Certificate">
|
|
||||||
</x-modal-confirmation>
|
|
||||||
<x-modal-confirmation title="Confirm Regenerate Certificate?" buttonTitle="Regenerate Certificate"
|
|
||||||
submitAction="regenerateCaCertificate" :actions="[
|
|
||||||
'This will generate a new CA certificate at /data/coolify/ssl/coolify-ca.crt and replace the existing one.',
|
|
||||||
'This will regenerate all SSL certificates for databases on this server and it will sign them with the new CA certificate.',
|
|
||||||
'You must manually redeploy all your databases on this server so that they use the new SSL certificates singned with the new CA certificate.',
|
|
||||||
'Because of caching, you probably also need to redeploy all your resources on this server that are using this CA certificate.',
|
|
||||||
]"
|
|
||||||
confirmationText="/data/coolify/ssl/coolify-ca.crt" shortConfirmationLabel="CA Certificate Path"
|
|
||||||
step3ButtonText="Regenerate Certificate">
|
|
||||||
</x-modal-confirmation>
|
|
||||||
</div>
|
|
||||||
<div class="space-y-4">
|
|
||||||
<div class="text-sm">
|
|
||||||
<p class="font-medium mb-2">Recommended Configuration:</p>
|
|
||||||
<ul class="list-disc pl-5 space-y-1">
|
|
||||||
<li>Mount this CA certificate of Coolify into all containers that need to connect to one of
|
|
||||||
your databases over SSL. You can see and copy the bind mount below.</li>
|
|
||||||
<li>Read more when and why this is needed <a class="underline"
|
|
||||||
href="https://coolify.io/docs/databases/ssl" target="_blank">here</a>.</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="relative">
|
|
||||||
<x-forms.copy-button
|
|
||||||
text="- /data/coolify/ssl/coolify-ca.crt:/etc/ssl/certs/coolify-ca.crt:ro" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<div class="flex items-center justify-between mb-2">
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<span class="text-sm">CA Certificate</span>
|
|
||||||
@if ($certificateValidUntil)
|
|
||||||
<span class="text-sm">(Valid until:
|
|
||||||
@if (now()->gt($certificateValidUntil))
|
|
||||||
<span class="text-red-500">{{ $certificateValidUntil->format('d.m.Y H:i:s') }} -
|
|
||||||
Expired)</span>
|
|
||||||
@elseif(now()->addDays(30)->gt($certificateValidUntil))
|
|
||||||
<span class="text-red-500">{{ $certificateValidUntil->format('d.m.Y H:i:s') }} -
|
|
||||||
Expiring soon)</span>
|
|
||||||
@else
|
|
||||||
<span>{{ $certificateValidUntil->format('d.m.Y H:i:s') }})</span>
|
|
||||||
@endif
|
|
||||||
</span>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
<x-forms.button wire:click="toggleCertificate" type="button" class="py-1! px-2! text-sm">
|
|
||||||
{{ $showCertificate ? 'Hide' : 'Show' }}
|
|
||||||
</x-forms.button>
|
|
||||||
</div>
|
|
||||||
@if ($showCertificate)
|
|
||||||
<textarea class="w-full h-[370px] input" wire:model="certificateContent"
|
|
||||||
placeholder="Paste or edit CA certificate content here..."></textarea>
|
|
||||||
@else
|
|
||||||
<div class="w-full h-[370px] input">
|
|
||||||
<div class="h-full flex flex-col items-center justify-center text-gray-300">
|
|
||||||
<div class="mb-2">
|
|
||||||
━━━━━━━━ CERTIFICATE CONTENT ━━━━━━━━
|
|
||||||
</div>
|
|
||||||
<div class="text-sm">
|
|
||||||
Click "Show" to view or edit
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@endif
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,88 @@
|
|||||||
|
<div>
|
||||||
|
<x-slot:title>
|
||||||
|
{{ data_get_str($server, 'name')->limit(10) }} > CA Certificate | Coolify
|
||||||
|
</x-slot>
|
||||||
|
<x-server.navbar :server="$server" />
|
||||||
|
<div class="flex flex-col h-full gap-8 sm:flex-row">
|
||||||
|
<x-server.sidebar :server="$server" activeMenu="ca-certificate" />
|
||||||
|
<div class="flex flex-col gap-4">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<h3>CA SSL Certificate</h3>
|
||||||
|
<div class="flex gap-2">
|
||||||
|
<x-modal-confirmation title="Confirm changing of CA Certificate?" buttonTitle="Save"
|
||||||
|
submitAction="saveCaCertificate" :actions="[
|
||||||
|
'This will overwrite the existing CA certificate at /data/coolify/ssl/coolify-ca.crt with your custom CA certificate.',
|
||||||
|
'This will regenerate all SSL certificates for databases on this server and it will sign them with your custom CA.',
|
||||||
|
'You must manually redeploy all your databases on this server so that they use the new SSL certificates singned with your new CA certificate.',
|
||||||
|
'Because of caching, you probably also need to redeploy all your resources on this server that are using this CA certificate.',
|
||||||
|
]"
|
||||||
|
confirmationText="/data/coolify/ssl/coolify-ca.crt" shortConfirmationLabel="CA Certificate Path"
|
||||||
|
step3ButtonText="Save Certificate">
|
||||||
|
</x-modal-confirmation>
|
||||||
|
<x-modal-confirmation title="Confirm Regenerate Certificate?" buttonTitle="Regenerate "
|
||||||
|
submitAction="regenerateCaCertificate" :actions="[
|
||||||
|
'This will generate a new CA certificate at /data/coolify/ssl/coolify-ca.crt and replace the existing one.',
|
||||||
|
'This will regenerate all SSL certificates for databases on this server and it will sign them with the new CA certificate.',
|
||||||
|
'You must manually redeploy all your databases on this server so that they use the new SSL certificates singned with the new CA certificate.',
|
||||||
|
'Because of caching, you probably also need to redeploy all your resources on this server that are using this CA certificate.',
|
||||||
|
]"
|
||||||
|
confirmationText="/data/coolify/ssl/coolify-ca.crt" shortConfirmationLabel="CA Certificate Path"
|
||||||
|
step3ButtonText="Regenerate Certificate">
|
||||||
|
</x-modal-confirmation>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="space-y-4">
|
||||||
|
<div class="text-sm">
|
||||||
|
<p class="font-medium mb-2">Recommended Configuration:</p>
|
||||||
|
<ul class="list-disc pl-5 space-y-1">
|
||||||
|
<li>Mount this CA certificate of Coolify into all containers that need to connect to one of
|
||||||
|
your databases over SSL. You can see and copy the bind mount below.</li>
|
||||||
|
<li>Read more when and why this is needed <a class="underline dark:text-white"
|
||||||
|
href="https://coolify.io/docs/databases/ssl" target="_blank">here</a>.</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="relative">
|
||||||
|
<x-forms.copy-button text="- /data/coolify/ssl/coolify-ca.crt:/etc/ssl/certs/coolify-ca.crt:ro" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="flex items-center justify-between mb-2">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<span class="text-sm">CA Certificate</span>
|
||||||
|
@if ($certificateValidUntil)
|
||||||
|
<span class="text-sm">(Valid until:
|
||||||
|
@if (now()->gt($certificateValidUntil))
|
||||||
|
<span class="text-red-500">{{ $certificateValidUntil->format('d.m.Y H:i:s') }} -
|
||||||
|
Expired)</span>
|
||||||
|
@elseif(now()->addDays(30)->gt($certificateValidUntil))
|
||||||
|
<span class="text-red-500">{{ $certificateValidUntil->format('d.m.Y H:i:s') }} -
|
||||||
|
Expiring soon)</span>
|
||||||
|
@else
|
||||||
|
<span>{{ $certificateValidUntil->format('d.m.Y H:i:s') }})</span>
|
||||||
|
@endif
|
||||||
|
</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
<x-forms.button wire:click="toggleCertificate" type="button" class="py-1! px-2! text-sm">
|
||||||
|
{{ $showCertificate ? 'Hide' : 'Show' }}
|
||||||
|
</x-forms.button>
|
||||||
|
</div>
|
||||||
|
@if ($showCertificate)
|
||||||
|
<textarea class="w-full h-[370px] input" wire:model="certificateContent"
|
||||||
|
placeholder="Paste or edit CA certificate content here..."></textarea>
|
||||||
|
@else
|
||||||
|
<div class="w-full h-[370px] input">
|
||||||
|
<div class="h-full flex flex-col items-center justify-center text-gray-300">
|
||||||
|
<div class="mb-2">
|
||||||
|
━━━━━━━━ CERTIFICATE CONTENT ━━━━━━━━
|
||||||
|
</div>
|
||||||
|
<div class="text-sm">
|
||||||
|
Click "Show" to view or edit
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -37,6 +37,7 @@ use App\Livewire\Security\ApiTokens;
|
|||||||
use App\Livewire\Security\PrivateKey\Index as SecurityPrivateKeyIndex;
|
use App\Livewire\Security\PrivateKey\Index as SecurityPrivateKeyIndex;
|
||||||
use App\Livewire\Security\PrivateKey\Show as SecurityPrivateKeyShow;
|
use App\Livewire\Security\PrivateKey\Show as SecurityPrivateKeyShow;
|
||||||
use App\Livewire\Server\Advanced as ServerAdvanced;
|
use App\Livewire\Server\Advanced as ServerAdvanced;
|
||||||
|
use App\Livewire\Server\CaCertificate\Show as CaCertificateShow;
|
||||||
use App\Livewire\Server\Charts as ServerCharts;
|
use App\Livewire\Server\Charts as ServerCharts;
|
||||||
use App\Livewire\Server\CloudflareTunnels;
|
use App\Livewire\Server\CloudflareTunnels;
|
||||||
use App\Livewire\Server\Delete as DeleteServer;
|
use App\Livewire\Server\Delete as DeleteServer;
|
||||||
@@ -242,6 +243,7 @@ Route::middleware(['auth', 'verified'])->group(function () {
|
|||||||
Route::get('/', ServerShow::class)->name('server.show');
|
Route::get('/', ServerShow::class)->name('server.show');
|
||||||
Route::get('/advanced', ServerAdvanced::class)->name('server.advanced');
|
Route::get('/advanced', ServerAdvanced::class)->name('server.advanced');
|
||||||
Route::get('/private-key', PrivateKeyShow::class)->name('server.private-key');
|
Route::get('/private-key', PrivateKeyShow::class)->name('server.private-key');
|
||||||
|
Route::get('/ca-certificate', CaCertificateShow::class)->name('server.ca-certificate');
|
||||||
Route::get('/resources', ResourcesShow::class)->name('server.resources');
|
Route::get('/resources', ResourcesShow::class)->name('server.resources');
|
||||||
Route::get('/cloudflare-tunnels', CloudflareTunnels::class)->name('server.cloudflare-tunnels');
|
Route::get('/cloudflare-tunnels', CloudflareTunnels::class)->name('server.cloudflare-tunnels');
|
||||||
Route::get('/destinations', ServerDestinations::class)->name('server.destinations');
|
Route::get('/destinations', ServerDestinations::class)->name('server.destinations');
|
||||||
|
|||||||
Reference in New Issue
Block a user