$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); } } }