feat: Update Proxmox extension with various improvements and bug fixes

- Change listStates method to accept nullable integer for limit parameter.
- Modify TechnitiumDns class to return structured error messages on failure.
- Enhance VNC and xterm popup routes with user authorization checks.
- Update backups view to improve loading states and add unique keys for dynamic elements.
- Refactor cloud-init view to ensure proper data binding and improve user experience.
- Add wire:key attributes to various elements in views for better Livewire performance.
- Improve error handling and user feedback in the firewall view.
- Update server overview and statistics views to handle potential null values gracefully.
- Add new migration files to extend database schema with user-set icons and notes for Proxmox nodes.
This commit is contained in:
2026-02-23 17:23:01 -05:00
parent 9aff64be93
commit f394483daa
48 changed files with 442 additions and 268 deletions

View File

@@ -30,7 +30,7 @@ class Component extends BaseComponent
public function mount(Server $server): void
{
$this->server = $server;
if ($server->user_id != auth()->id()) {
if ((int) $server->user_id !== (int) auth()->id()) {
abort(403);
}
@@ -65,14 +65,9 @@ class Component extends BaseComponent
['vmid' => $this->server->vm_id]
);
if ($response->successful()) {
$this->notify('Action performed successfully', 'success');
if (property_exists($this, 'fastPolling')) {
$this->fastPolling = true;
}
} else {
$message = $response->json()['errors'][0]['message'] ?? 'Unknown error';
$this->notify('Action failed: ' . $message, 'error');
$this->notify('Action performed successfully', 'success');
if (property_exists($this, 'fastPolling')) {
$this->fastPolling = true;
}
} catch (\Throwable $e) {
$this->notify('Action failed: ' . $e->getMessage(), 'error');
@@ -106,11 +101,7 @@ class Component extends BaseComponent
'/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/config'
);
if (!$configResponse->successful()) {
// If we can't check, allow the action (fail open)
return true;
}
// Note: request() calls ->throw(), so response is always successful here
$config = $configResponse->json()['data'] ?? [];
$totalStorage = $this->calculateTotalStorage($config);
@@ -234,8 +225,9 @@ class Component extends BaseComponent
data: ['vmid' => $this->server->vm_id]
);
if (isset($storageContent['data']) && is_array($storageContent['data'])) {
foreach ($storageContent['data'] as $item) {
$data = $storageContent->json()['data'] ?? [];
if (is_array($data)) {
foreach ($data as $item) {
if (isset($item['volid']) && $item['volid'] === $volume) {
// Size is in bytes
if (isset($item['size'])) {
@@ -263,19 +255,8 @@ class Component extends BaseComponent
'/nodes/' . $this->server->node->name . '/qemu/' . $this->server->vm_id . '/status/current'
);
if ($response->successful()) {
$data = $response->json()['data'] ?? null;
$this->status = $data ? (object) $data : null;
} else {
\Log::warning('Failed to load VM status for server ' . $this->server->id, [
'server_id' => $this->server->id,
'vm_id' => $this->server->vm_id,
'node' => $this->server->node->name,
'status_code' => $response->status(),
'response' => $response->json(),
]);
$this->status = null;
}
$data = $response->json()['data'] ?? null;
$this->status = $data ? (object) $data : null;
} catch (\Illuminate\Http\Client\ConnectionException $e) {
// Timeout or connection error - don't log as error, just set status to null
\Log::info('Connection timeout loading VM status for server ' . $this->server->id);