Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Jh8RnYXrC8E6z79LWs8ggd
159 lines
8.1 KiB
PHP
159 lines
8.1 KiB
PHP
<?php
|
|
|
|
namespace Dashboard\Unifi\Http\Controllers;
|
|
|
|
use App\Models\Setting;
|
|
use Dashboard\Unifi\Services\UnifiApiClient;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Routing\Controller;
|
|
use Inertia\Inertia;
|
|
|
|
class UnifiSettingsController extends Controller
|
|
{
|
|
public function edit(?string $tab = null)
|
|
{
|
|
return Inertia::render('Unifi/Settings', [
|
|
'activeTab' => $tab,
|
|
'controllerUrl' => Setting::get('unifi.controller_url', ''),
|
|
'hasApiKey' => (bool) Setting::get('unifi.api_key'),
|
|
'site' => Setting::get('unifi.site', 'default'),
|
|
'pollInterval' => (int) Setting::get('unifi.poll_interval', 30),
|
|
'cacheTtl' => (int) Setting::get('unifi.cache_ttl', 30),
|
|
'retentionDays' => (int) Setting::get('unifi.retention_days', 30),
|
|
'autoRebootEnabled' => (bool) Setting::get('unifi.auto_reboot.enabled', false),
|
|
'autoRebootFrequency' => Setting::get('unifi.auto_reboot.frequency', 'daily'),
|
|
'autoRebootDow' => (int) Setting::get('unifi.auto_reboot.day_of_week', 0),
|
|
'autoRebootHour' => (int) Setting::get('unifi.auto_reboot.hour', 2),
|
|
'autoRebootMinute' => (int) Setting::get('unifi.auto_reboot.minute', 0),
|
|
'rotationEnabled' => (bool) Setting::get('unifi.password_rotation.enabled', false),
|
|
'rotationFrequency' => Setting::get('unifi.password_rotation.frequency', 'weekly'),
|
|
'rotationDow' => (int) Setting::get('unifi.password_rotation.day_of_week', 0),
|
|
'rotationHour' => (int) Setting::get('unifi.password_rotation.hour', 2),
|
|
'rotationMinute' => (int) Setting::get('unifi.password_rotation.minute', 0),
|
|
'rotationWordlist' => Setting::get('unifi.password_rotation.wordlist', ''),
|
|
'rotationLastRotatedAt' => Setting::get('unifi.password_rotation.last_rotated_at', null),
|
|
'rotationLastPassword' => Setting::get('unifi.password_rotation.last_password', null),
|
|
'ppskSchedulingEnabled' => (bool) Setting::get('unifi.ppsk_scheduling.enabled', false),
|
|
'apiEnabled' => (bool) Setting::get('unifi.api.enabled', false),
|
|
'apiToken' => Setting::get('unifi.api_token', null),
|
|
]);
|
|
}
|
|
|
|
public function regenerateApiToken()
|
|
{
|
|
$token = bin2hex(random_bytes(24));
|
|
Setting::set('unifi.api_token', $token);
|
|
return response()->json(['token' => $token]);
|
|
}
|
|
|
|
public function clearApiToken()
|
|
{
|
|
Setting::set('unifi.api_token', '');
|
|
return response()->json(['ok' => true]);
|
|
}
|
|
|
|
public function update(Request $request)
|
|
{
|
|
$request->validate([
|
|
'controller_url' => 'required|url|max:500',
|
|
'api_key' => 'nullable|string|max:500',
|
|
'site' => 'required|string|max:100',
|
|
'poll_interval' => 'nullable|integer|min:5|max:300',
|
|
'cache_ttl' => 'nullable|integer|min:5|max:300',
|
|
'retention_days' => 'nullable|integer|min:1|max:365',
|
|
'auto_reboot_enabled' => 'boolean',
|
|
'auto_reboot_frequency' => 'in:daily,weekly',
|
|
'auto_reboot_dow' => 'nullable|integer|min:0|max:6',
|
|
'auto_reboot_hour' => 'nullable|integer|min:0|max:23',
|
|
'auto_reboot_minute' => 'nullable|integer|min:0|max:59',
|
|
'rotation_enabled' => 'boolean',
|
|
'rotation_frequency' => 'in:daily,weekly',
|
|
'rotation_dow' => 'nullable|integer|min:0|max:6',
|
|
'rotation_hour' => 'nullable|integer|min:0|max:23',
|
|
'rotation_minute' => 'nullable|integer|min:0|max:59',
|
|
'rotation_wordlist' => 'nullable|string|max:20000',
|
|
'ppsk_scheduling_enabled' => 'boolean',
|
|
'api_enabled' => 'boolean',
|
|
]);
|
|
|
|
Setting::set('unifi.controller_url', rtrim($request->controller_url, '/'));
|
|
Setting::set('unifi.site', $request->site);
|
|
|
|
if ($request->api_key && $request->api_key !== '••••••••') {
|
|
Setting::set('unifi.api_key', $request->api_key);
|
|
}
|
|
|
|
if ($request->has('poll_interval')) Setting::set('unifi.poll_interval', $request->poll_interval ?? 30);
|
|
if ($request->has('cache_ttl')) Setting::set('unifi.cache_ttl', $request->cache_ttl ?? 30);
|
|
if ($request->has('retention_days')) Setting::set('unifi.retention_days', $request->retention_days ?? 30);
|
|
|
|
Setting::set('unifi.auto_reboot.enabled', $request->boolean('auto_reboot_enabled') ? '1' : '');
|
|
Setting::set('unifi.auto_reboot.frequency', $request->input('auto_reboot_frequency', 'daily'));
|
|
Setting::set('unifi.auto_reboot.day_of_week',$request->input('auto_reboot_dow', 0));
|
|
Setting::set('unifi.auto_reboot.hour', $request->input('auto_reboot_hour', 2));
|
|
Setting::set('unifi.auto_reboot.minute', $request->input('auto_reboot_minute', 0));
|
|
|
|
Setting::set('unifi.password_rotation.enabled', $request->boolean('rotation_enabled') ? '1' : '');
|
|
Setting::set('unifi.password_rotation.frequency', $request->input('rotation_frequency', 'weekly'));
|
|
Setting::set('unifi.password_rotation.day_of_week', $request->input('rotation_dow', 0));
|
|
Setting::set('unifi.password_rotation.hour', $request->input('rotation_hour', 2));
|
|
Setting::set('unifi.password_rotation.minute', $request->input('rotation_minute', 0));
|
|
Setting::set('unifi.password_rotation.wordlist', $request->input('rotation_wordlist', ''));
|
|
Setting::set('unifi.ppsk_scheduling.enabled', $request->boolean('ppsk_scheduling_enabled') ? '1' : '');
|
|
Setting::set('unifi.api.enabled', $request->boolean('api_enabled') ? '1' : '');
|
|
|
|
\Illuminate\Support\Facades\Cache::forget('unifi:api_prefix:' . md5(rtrim($request->controller_url, '/')));
|
|
|
|
return back()->with('success', 'UniFi settings saved.');
|
|
}
|
|
|
|
public function testConnection(UnifiApiClient $unifi)
|
|
{
|
|
try {
|
|
$info = $unifi->testConnection();
|
|
$version = $info[0]['version'] ?? 'unknown';
|
|
return response()->json(['ok' => true, 'version' => $version]);
|
|
} catch (\Throwable $e) {
|
|
return response()->json(['ok' => false, 'error' => $e->getMessage()], 422);
|
|
}
|
|
}
|
|
|
|
public function fetchSites(Request $request, UnifiApiClient $unifi)
|
|
{
|
|
$request->validate([
|
|
'controller_url' => 'required|url',
|
|
]);
|
|
|
|
$url = rtrim($request->controller_url, '/');
|
|
$user = $request->input('username', '');
|
|
$pass = $request->input('password', '');
|
|
$key = $request->input('api_key', '');
|
|
|
|
// Use saved credentials if placeholders sent
|
|
if ($pass === '••••••••') $pass = Setting::get('unifi.password', '');
|
|
if ($key === '••••••••') $key = Setting::get('unifi.api_key', '');
|
|
|
|
try {
|
|
$sites = $unifi->getSites($url, $user ?: null, $pass ?: null, $key ?: null);
|
|
return response()->json([
|
|
'ok' => true,
|
|
'sites' => collect($sites)->map(fn ($s) => [
|
|
'name' => $s['name'] ?? 'default',
|
|
'desc' => $s['desc'] ?? $s['name'] ?? 'Default',
|
|
])->values(),
|
|
]);
|
|
} catch (\Throwable $e) {
|
|
$hint = "Tried URL: {$url}. ";
|
|
if (str_contains($url, 'unifi.ui.com')) {
|
|
$hint .= "Use your console's direct URL (*.id.ui.direct or local IP) instead of unifi.ui.com.";
|
|
} elseif (! $key) {
|
|
$hint .= "Enter an API key above.";
|
|
} else {
|
|
$hint .= "Check that the API key is correct and the controller URL is reachable.";
|
|
}
|
|
|
|
return response()->json(['ok' => false, 'error' => $e->getMessage(), 'hint' => $hint], 422);
|
|
}
|
|
}
|
|
}
|