FabioFratini преди 6 месеца
родител
ревизия
813b67b0a0

+ 0 - 98
app/Http/Controllers/VpnController.php

@@ -1,98 +0,0 @@
-<?php
-
-namespace App\Http\Controllers;
-
-use Illuminate\Http\Request;
-use App\Services\VpnManager;
-use Illuminate\Support\Facades\Validator;
-
-class VpnController extends Controller
-{
-    private $vpnManager;
-
-    public function __construct(VpnManager $vpnManager)
-    {
-        $this->vpnManager = $vpnManager;
-    }
-
-    public function showCredentialsForm()
-    {
-        $status = $this->vpnManager->getVpnStatus();
-        return view('vpn.credentials', compact('status'));
-    }
-
-    public function updateCredentials(Request $request)
-    {
-        $validator = Validator::make($request->all(), [
-            'username' => 'required|string',
-            'password' => 'required|string',
-            'server' => 'required|string',
-        ]);
-
-        if ($validator->fails()) {
-            return redirect()->back()
-                ->withErrors($validator)
-                ->withInput();
-        }
-
-        $success = $this->vpnManager->updateCredentials(
-            $request->username,
-            $request->password,
-            $request->server
-        );
-
-        if ($success) {
-            return redirect()->back()->with('success', 'Credenziali VPN aggiornate con successo!');
-        } else {
-            return redirect()->back()->with('error', 'Errore nell\'aggiornamento delle credenziali VPN.');
-        }
-    }
-
-    public function getStatus()
-    {
-        $status = $this->vpnManager->getVpnStatus();
-        $lastUpdate = $this->vpnManager->getLastUpdate();
-
-        return response()->json([
-            'status' => $status,
-            'last_update' => $lastUpdate
-        ]);
-    }
-
-    public function connect()
-    {
-        try {
-            $result = $this->vpnManager->connectVpn();
-
-            if ($result) {
-                return response()->json(['success' => true, 'message' => 'Connessione VPN avviata']);
-            } else {
-                return response()->json(['success' => false, 'message' => 'Errore nella connessione VPN']);
-            }
-        } catch (\Exception $e) {
-            return response()->json(['success' => false, 'message' => 'Errore: ' . $e->getMessage()]);
-        }
-    }
-
-    public function disconnect()
-    {
-        try {
-            $result = $this->vpnManager->disconnectVpn();
-
-            if ($result) {
-                return response()->json(['success' => true, 'message' => 'Disconnessione VPN avviata']);
-            } else {
-                return response()->json(['success' => false, 'message' => 'Errore nella disconnessione VPN']);
-            }
-        } catch (\Exception $e) {
-            return response()->json(['success' => false, 'message' => 'Errore: ' . $e->getMessage()]);
-        }
-    }
-
-        public function showManagementPage()
-    {
-        $status = $this->vpnManager->getVpnStatus();
-        $lastUpdate = $this->vpnManager->getLastUpdate();
-        return view('vpn.management', compact('status', 'lastUpdate'));
-    }
-}

+ 173 - 0
app/Http/Livewire/VpnManagement.php

@@ -0,0 +1,173 @@
+<?php
+
+namespace App\Http\Livewire;
+
+use Livewire\Component;
+use App\Services\VpnManager;
+use Illuminate\Support\Facades\Log;
+
+class VpnManagement extends Component
+{
+    public $username = 'com.cmrmp013.0001';
+    public $password = '';
+    public $server = 'anyvpn.ilportaledellautomobilista.it/utentiMCTC';
+    public $vpnStatus = 'unknown';
+    public $lastUpdate = null;
+    public $successMessage = '';
+    public $errorMessage = '';
+
+    protected $rules = [
+        'username' => 'required|string',
+        'password' => 'required|string',
+        'server' => 'required|string',
+    ];
+
+    protected $vpnManager;
+
+    public function boot(VpnManager $vpnManager)
+    {
+        $this->vpnManager = $vpnManager;
+    }
+
+    public function mount()
+    {
+        $this->refreshStatus();
+    }
+
+    public function render()
+    {
+        return view('livewire.vpn-management');
+    }
+
+    public function refreshStatus()
+    {
+        $this->vpnStatus = $this->vpnManager->getVpnStatus();
+        $this->lastUpdate = $this->vpnManager->getLastUpdate();
+        $this->emit('vpnStatusUpdated', $this->vpnStatus);
+    }
+
+    public function updateCredentials()
+    {
+        $this->validate();
+
+        try {
+            $success = $this->vpnManager->updateCredentials(
+                $this->username,
+                $this->password,
+                $this->server
+            );
+
+            if ($success) {
+                $this->successMessage = 'Credenziali VPN aggiornate con successo!';
+                $this->errorMessage = '';
+                $this->password = ''; // Clear password field for security
+
+                // Emit event for JavaScript notification
+                $this->emit('showToast', 'success', 'Credenziali VPN aggiornate con successo!');
+
+                Log::info('VPN credentials updated successfully');
+            } else {
+                $this->errorMessage = 'Errore nell\'aggiornamento delle credenziali VPN.';
+                $this->successMessage = '';
+                $this->emit('showToast', 'error', 'Errore nell\'aggiornamento delle credenziali VPN.');
+            }
+        } catch (\Exception $e) {
+            $this->errorMessage = 'Errore: ' . $e->getMessage();
+            $this->successMessage = '';
+            $this->emit('showToast', 'error', 'Errore: ' . $e->getMessage());
+            Log::error('Error updating VPN credentials: ' . $e->getMessage());
+        }
+    }
+
+    public function connectVpn()
+    {
+        try {
+            $result = $this->vpnManager->connectVpn();
+
+            if ($result) {
+                $this->emit('showToast', 'success', 'Comando di connessione VPN inviato!');
+                Log::info('VPN connection command sent');
+
+                // Refresh status after a delay
+                $this->emit('refreshStatusDelayed');
+            } else {
+                $this->emit('showToast', 'error', 'Errore nel lancio della connessione VPN');
+                Log::error('Failed to send VPN connection command');
+            }
+        } catch (\Exception $e) {
+            $this->emit('showToast', 'error', 'Errore: ' . $e->getMessage());
+            Log::error('Error connecting VPN: ' . $e->getMessage());
+        }
+    }
+
+    public function disconnectVpn()
+    {
+        try {
+            $result = $this->vpnManager->disconnectVpn();
+
+            if ($result) {
+                $this->emit('showToast', 'success', 'Comando di disconnessione VPN inviato!');
+                Log::info('VPN disconnection command sent');
+
+                // Refresh status after a delay
+                $this->emit('refreshStatusDelayed');
+            } else {
+                $this->emit('showToast', 'error', 'Errore nella disconnessione VPN');
+                Log::error('Failed to send VPN disconnection command');
+            }
+        } catch (\Exception $e) {
+            $this->emit('showToast', 'error', 'Errore: ' . $e->getMessage());
+            Log::error('Error disconnecting VPN: ' . $e->getMessage());
+        }
+    }
+
+    public function getStatusBadgeClass()
+    {
+        return match($this->vpnStatus) {
+            'connected' => 'badge badge-success',
+            'disconnected' => 'badge badge-danger',
+            'error' => 'badge badge-danger',
+            default => 'badge badge-warning'
+        };
+    }
+
+    public function getStatusBadgeText()
+    {
+        return match($this->vpnStatus) {
+            'connected' => 'ON',
+            'disconnected' => 'OFF',
+            'error' => 'ERR',
+            default => '?'
+        };
+    }
+
+    public function getStatusIconClass()
+    {
+        return match($this->vpnStatus) {
+            'connected' => 'info-box-icon bg-success',
+            'disconnected' => 'info-box-icon bg-danger',
+            'error' => 'info-box-icon bg-danger',
+            default => 'info-box-icon bg-warning'
+        };
+    }
+
+    public function getStatusIcon()
+    {
+        return match($this->vpnStatus) {
+            'connected' => 'fas fa-check',
+            'disconnected' => 'fas fa-times',
+            'error' => 'fas fa-exclamation-triangle',
+            default => 'fas fa-question'
+        };
+    }
+
+    public function getStatusText()
+    {
+        return match($this->vpnStatus) {
+            'connected' => 'Connesso',
+            'disconnected' => 'Disconnesso',
+            'error' => 'Errore',
+            default => 'Sconosciuto'
+        };
+    }
+}

+ 273 - 0
resources/views/livewire/vpn-management.blade.php

@@ -0,0 +1,273 @@
+<!-- resources/views/livewire/vpn-management.blade.php -->
+<div>
+    <!-- Content Header -->
+    <div class="content-header">
+        <div class="container-fluid">
+            <div class="row mb-2">
+                <div class="col-sm-6">
+                    <h1 class="m-0">Gestione Connessione VPN</h1>
+                </div>
+                <div class="col-sm-6">
+                    <ol class="breadcrumb float-sm-right">
+                        <li class="breadcrumb-item"><a href="/dashboard">Home</a></li>
+                        <li class="breadcrumb-item active">VPN</li>
+                    </ol>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- Main content -->
+    <div class="row">
+        <!-- Stato VPN -->
+        <div class="col-md-6">
+            <div class="card card-primary">
+                <div class="card-header">
+                    <h3 class="card-title">
+                        <i class="fas fa-shield-alt"></i> Stato Connessione VPN
+                    </h3>
+                    <div class="card-tools">
+                        <button type="button" class="btn btn-tool" wire:click="refreshStatus">
+                            <i class="fas fa-sync"></i>
+                        </button>
+                    </div>
+                </div>
+                <div class="card-body">
+                    <div class="row">
+                        <div class="col-md-6">
+                            <div class="info-box">
+                                <span class="{{ $this->getStatusIconClass() }}">
+                                    <i class="{{ $this->getStatusIcon() }}"></i>
+                                </span>
+                                <div class="info-box-content">
+                                    <span class="info-box-text">Stato VPN</span>
+                                    <span class="info-box-number">{{ $this->getStatusText() }}</span>
+                                    <span class="info-box-more">
+                                        @if($lastUpdate)
+                                            Ultimo aggiornamento: {{ \Carbon\Carbon::parse($lastUpdate)->format('d/m/Y H:i:s') }}
+                                        @else
+                                            Nessun aggiornamento disponibile
+                                        @endif
+                                    </span>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="col-md-6">
+                            <div class="text-center">
+                                <button type="button"
+                                        class="btn btn-success btn-lg"
+                                        wire:click="connectVpn"
+                                        wire:loading.attr="disabled"
+                                        wire:target="connectVpn">
+                                    <span wire:loading.remove wire:target="connectVpn">
+                                        <i class="fas fa-play"></i> Connetti VPN
+                                    </span>
+                                    <span wire:loading wire:target="connectVpn">
+                                        <i class="fas fa-spinner fa-spin"></i> Connettendo...
+                                    </span>
+                                </button>
+                                <br><br>
+                                <button type="button"
+                                        class="btn btn-warning btn-lg"
+                                        wire:click="disconnectVpn"
+                                        wire:loading.attr="disabled"
+                                        wire:target="disconnectVpn">
+                                    <span wire:loading.remove wire:target="disconnectVpn">
+                                        <i class="fas fa-stop"></i> Disconnetti VPN
+                                    </span>
+                                    <span wire:loading wire:target="disconnectVpn">
+                                        <i class="fas fa-spinner fa-spin"></i> Disconnettendo...
+                                    </span>
+                                </button>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+
+        <!-- Configurazione Credenziali -->
+        <div class="col-md-6">
+            <div class="card card-warning">
+                <div class="card-header">
+                    <h3 class="card-title">
+                        <i class="fas fa-cog"></i> Configurazione Credenziali
+                    </h3>
+                </div>
+                <div class="card-body">
+                    @if($successMessage)
+                        <div class="alert alert-success alert-dismissible">
+                            <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
+                            {{ $successMessage }}
+                        </div>
+                    @endif
+
+                    @if($errorMessage)
+                        <div class="alert alert-danger alert-dismissible">
+                            <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
+                            {{ $errorMessage }}
+                        </div>
+                    @endif
+
+                    <form wire:submit.prevent="updateCredentials">
+                        <div class="form-group">
+                            <label for="username">Username</label>
+                            <input type="text"
+                                   class="form-control @error('username') is-invalid @enderror"
+                                   wire:model="username"
+                                   required>
+                            @error('username')
+                                <div class="invalid-feedback">{{ $message }}</div>
+                            @enderror
+                        </div>
+
+                        <div class="form-group">
+                            <label for="password">Password</label>
+                            <input type="password"
+                                   class="form-control @error('password') is-invalid @enderror"
+                                   wire:model="password"
+                                   placeholder="Inserisci la password"
+                                   required>
+                            @error('password')
+                                <div class="invalid-feedback">{{ $message }}</div>
+                            @enderror
+                        </div>
+
+                        <div class="form-group">
+                            <label for="server">Server VPN</label>
+                            <input type="text"
+                                   class="form-control @error('server') is-invalid @enderror"
+                                   wire:model="server"
+                                   required>
+                            @error('server')
+                                <div class="invalid-feedback">{{ $message }}</div>
+                            @enderror
+                        </div>
+
+                        <button type="submit"
+                                class="btn btn-primary"
+                                wire:loading.attr="disabled"
+                                wire:target="updateCredentials">
+                            <span wire:loading.remove wire:target="updateCredentials">
+                                <i class="fas fa-save"></i> Salva Credenziali
+                            </span>
+                            <span wire:loading wire:target="updateCredentials">
+                                <i class="fas fa-spinner fa-spin"></i> Salvando...
+                            </span>
+                        </button>
+                    </form>
+                </div>
+            </div>
+        </div>
+    </div>
+
+    <!-- Log VPN -->
+    <div class="row mt-4">
+        <div class="col-md-12">
+            <div class="card card-info">
+                <div class="card-header">
+                    <h3 class="card-title">
+                        <i class="fas fa-file-alt"></i> Informazioni VPN
+                    </h3>
+                </div>
+                <div class="card-body">
+                    <div class="table-responsive">
+                        <table class="table table-striped">
+                            <thead>
+                                <tr>
+                                    <th>Proprietà</th>
+                                    <th>Valore</th>
+                                </tr>
+                            </thead>
+                            <tbody>
+                                <tr>
+                                    <td><strong>Stato Attuale</strong></td>
+                                    <td>
+                                        <span class="{{ $this->getStatusBadgeClass() }}">
+                                            {{ $this->getStatusBadgeText() }}
+                                        </span>
+                                        {{ $this->getStatusText() }}
+                                    </td>
+                                </tr>
+                                <tr>
+                                    <td><strong>Server Configurato</strong></td>
+                                    <td>{{ $server }}</td>
+                                </tr>
+                                <tr>
+                                    <td><strong>Username Configurato</strong></td>
+                                    <td>{{ $username }}</td>
+                                </tr>
+                                <tr>
+                                    <td><strong>Ultimo Aggiornamento</strong></td>
+                                    <td>
+                                        @if($lastUpdate)
+                                            {{ \Carbon\Carbon::parse($lastUpdate)->format('d/m/Y H:i:s') }}
+                                        @else
+                                            Non disponibile
+                                        @endif
+                                    </td>
+                                </tr>
+                            </tbody>
+                        </table>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+
+@push('css')
+<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css">
+@endpush
+
+@push('scripts')
+<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
+<script>
+    // Listen for Livewire events
+    document.addEventListener('livewire:load', function () {
+        // Auto-refresh status every 30 seconds
+        setInterval(function() {
+            @this.call('refreshStatus');
+        }, 30000);
+
+        // Update sidebar badge when status changes
+        Livewire.on('vpnStatusUpdated', status => {
+            updateSidebarBadge(status);
+        });
+
+        // Show toast notifications
+        Livewire.on('showToast', (type, message) => {
+            if (typeof toastr !== 'undefined') {
+                toastr[type](message);
+            }
+        });
+
+        // Refresh status with delay (after connect/disconnect commands)
+        Livewire.on('refreshStatusDelayed', () => {
+            setTimeout(function() {
+                @this.call('refreshStatus');
+            }, 3000);
+        });
+    });
+
+    function updateSidebarBadge(status) {
+        const badge = document.getElementById('vpn-status-badge');
+        if (badge) {
+            badge.className = ''; // Clear existing classes
+            if (status === 'connected') {
+                badge.className = 'badge badge-success right';
+                badge.textContent = 'ON';
+            } else if (status === 'disconnected') {
+                badge.className = 'badge badge-danger right';
+                badge.textContent = 'OFF';
+            } else if (status === 'error') {
+                badge.className = 'badge badge-danger right';
+                badge.textContent = 'ERR';
+            } else {
+                badge.className = 'badge badge-warning right';
+                badge.textContent = '?';
+            }
+        }
+    }
+</script>
+@endpush

+ 0 - 248
resources/views/vpn/management.blade.php

@@ -1,248 +0,0 @@
-
-<div class="content-header">
-    <div class="container-fluid">
-        <div class="row mb-2">
-            <div class="col-sm-6">
-                <h1 class="m-0">Gestione Connessione VPN</h1>
-            </div>
-            <div class="col-sm-6">
-                <ol class="breadcrumb float-sm-right">
-                    <li class="breadcrumb-item"><a href="/dashboard">Home</a></li>
-                    <li class="breadcrumb-item active">VPN</li>
-                </ol>
-            </div>
-        </div>
-    </div>
-</div>
-
-<!-- Main content -->
-<div class="row">
-    <!-- Stato VPN -->
-    <div class="col-md-6">
-        <div class="card card-primary">
-            <div class="card-header">
-                <h3 class="card-title">
-                    <i class="fas fa-shield-alt"></i> Stato Connessione VPN
-                </h3>
-            </div>
-            <div class="card-body">
-                <div class="row">
-                    <div class="col-md-6">
-                        <div class="info-box">
-                            <span class="info-box-icon bg-info" id="vpn-status-icon">
-                                <i class="fas fa-question"></i>
-                            </span>
-                            <div class="info-box-content">
-                                <span class="info-box-text">Stato VPN</span>
-                                <span class="info-box-number" id="vpn-status-text">Caricamento...</span>
-                                <span class="info-box-more" id="vpn-last-update">--</span>
-                            </div>
-                        </div>
-                    </div>
-                    <div class="col-md-6">
-                        <div class="text-center">
-                            <button type="button" class="btn btn-success btn-lg" id="connect-vpn-btn">
-                                <i class="fas fa-play"></i> Connetti VPN
-                            </button>
-                            <button type="button" class="btn btn-warning btn-lg mt-2" id="disconnect-vpn-btn">
-                                <i class="fas fa-stop"></i> Disconnetti VPN
-                            </button>
-                        </div>
-                    </div>
-                </div>
-            </div>
-        </div>
-    </div>
-
-    <!-- Configurazione Credenziali -->
-    <div class="col-md-6">
-        <div class="card card-warning">
-            <div class="card-header">
-                <h3 class="card-title">
-                    <i class="fas fa-cog"></i> Configurazione Credenziali
-                </h3>
-            </div>
-            <div class="card-body">
-                @if(session('success'))
-                    <div class="alert alert-success alert-dismissible">
-                        <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
-                        {{ session('success') }}
-                    </div>
-                @endif
-
-                <form action="/vpn/update-credentials" method="POST">
-                    @csrf
-                    <div class="form-group">
-                        <label for="username">Username</label>
-                        <input type="text" class="form-control" id="username" name="username"
-                               value="{{ old('username', 'com.cmrmp013.0001') }}" required>
-                    </div>
-                    <div class="form-group">
-                        <label for="password">Password</label>
-                        <input type="password" class="form-control" id="password" name="password"
-                               placeholder="Inserisci la password" required>
-                    </div>
-                    <div class="form-group">
-                        <label for="server">Server VPN</label>
-                        <input type="text" class="form-control" id="server" name="server"
-                               value="{{ old('server', 'anyvpn.ilportaledellautomobilista.it/utentiMCTC') }}" required>
-                    </div>
-                    <button type="submit" class="btn btn-primary">
-                        <i class="fas fa-save"></i> Salva Credenziali
-                    </button>
-                </form>
-            </div>
-        </div>
-    </div>
-</div>
-
-<!-- Log VPN -->
-<div class="row mt-4">
-    <div class="col-md-12">
-        <div class="card card-info">
-            <div class="card-header">
-                <h3 class="card-title">
-                    <i class="fas fa-file-alt"></i> Log Connessione VPN
-                </h3>
-                <div class="card-tools">
-                    <button type="button" class="btn btn-tool" id="refresh-logs">
-                        <i class="fas fa-sync"></i>
-                    </button>
-                </div>
-            </div>
-            <div class="card-body">
-                <div class="table-responsive">
-                    <table class="table table-striped">
-                        <thead>
-                            <tr>
-                                <th>Data/Ora</th>
-                                <th>Tipo</th>
-                                <th>Messaggio</th>
-                            </tr>
-                        </thead>
-                        <tbody id="vpn-logs-table">
-                            <tr>
-                                <td colspan="3" class="text-center">Caricamento logs...</td>
-                            </tr>
-                        </tbody>
-                    </table>
-                </div>
-            </div>
-        </div>
-    </div>
-</div>
-
-@push('css')
-<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css">
-@endpush
-
-@push('scripts')
-<script src="https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js"></script>
-<script>
-    $(document).ready(function() {
-        // Funzione per aggiornare lo stato VPN
-        function updateVpnStatus() {
-            $.ajax({
-                url: '/vpn/status',
-                type: 'GET',
-                success: function(data) {
-                    const status = data.status;
-                    const statusIcon = $('#vpn-status-icon i');
-                    const statusText = $('#vpn-status-text');
-                    const statusBadge = $('#vpn-status-badge');
-                    const lastUpdate = $('#vpn-last-update');
-
-                    // Aggiorna icona e testo in base al stato
-                    if (status === 'connected') {
-                        statusIcon.removeClass().addClass('fas fa-check');
-                        $('#vpn-status-icon').removeClass().addClass('info-box-icon bg-success');
-                        statusText.text('Connesso');
-                        if (statusBadge.length) statusBadge.removeClass().addClass('badge badge-success right').text('ON');
-                    } else if (status === 'disconnected') {
-                        statusIcon.removeClass().addClass('fas fa-times');
-                        $('#vpn-status-icon').removeClass().addClass('info-box-icon bg-danger');
-                        statusText.text('Disconnesso');
-                        if (statusBadge.length) statusBadge.removeClass().addClass('badge badge-danger right').text('OFF');
-                    } else {
-                        statusIcon.removeClass().addClass('fas fa-question');
-                        $('#vpn-status-icon').removeClass().addClass('info-box-icon bg-warning');
-                        statusText.text('Sconosciuto');
-                        if (statusBadge.length) statusBadge.removeClass().addClass('badge badge-warning right').text('?');
-                    }
-
-                    if (data.last_update) {
-                        lastUpdate.text('Ultimo aggiornamento: ' + new Date(data.last_update).toLocaleString());
-                    }
-                },
-                error: function() {
-                    $('#vpn-status-text').text('Errore nel recupero dello stato');
-                    const statusBadge = $('#vpn-status-badge');
-                    if (statusBadge.length) statusBadge.removeClass().addClass('badge badge-danger right').text('ERR');
-                }
-            });
-        }
-
-        // Funzione per connettere VPN
-        $('#connect-vpn-btn').click(function() {
-            const btn = $(this);
-            btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Connettendo...');
-
-            $.ajax({
-                url: '/vpn/connect',
-                type: 'POST',
-                data: {
-                    _token: '{{ csrf_token() }}'
-                },
-                success: function(data) {
-                    if (data.success) {
-                        toastr.success('Comando di connessione VPN inviato!');
-                        setTimeout(updateVpnStatus, 3000); // Aggiorna lo stato dopo 3 secondi
-                    } else {
-                        toastr.error('Errore nel lancio della connessione VPN');
-                    }
-                },
-                error: function() {
-                    toastr.error('Errore nel lancio della connessione VPN');
-                },
-                complete: function() {
-                    btn.prop('disabled', false).html('<i class="fas fa-play"></i> Connetti VPN');
-                }
-            });
-        });
-
-        // Funzione per disconnettere VPN
-        $('#disconnect-vpn-btn').click(function() {
-            const btn = $(this);
-            btn.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Disconnettendo...');
-
-            $.ajax({
-                url: '/vpn/disconnect',
-                type: 'POST',
-                data: {
-                    _token: '{{ csrf_token() }}'
-                },
-                success: function(data) {
-                    if (data.success) {
-                        toastr.success('Comando di disconnessione VPN inviato!');
-                        setTimeout(updateVpnStatus, 3000);
-                    } else {
-                        toastr.error('Errore nella disconnessione VPN');
-                    }
-                },
-                error: function() {
-                    toastr.error('Errore nella disconnessione VPN');
-                },
-                complete: function() {
-                    btn.prop('disabled', false).html('<i class="fas fa-stop"></i> Disconnetti VPN');
-                }
-            });
-        });
-
-        // Aggiorna lo stato all'avvio
-        updateVpnStatus();
-
-        // Aggiorna lo stato ogni 30 secondi
-        setInterval(updateVpnStatus, 30000);
-    });
-</script>
-@endpush