orderBy('name')->get(); $totalDevices = NetworkDevice::count(); $onlineDevices = NetworkDevice::where('status', 'online')->count(); $recentEvents = NetworkDeviceEvent::with('device') ->where('documented', false) ->latest() ->take(10) ->get(); // Letzten Scan pro Segment $latestScans = NetworkScan::select('network_scans.*') ->orderByDesc('created_at') ->get() ->groupBy('segment_id'); return view('network.dashboard', compact( 'segments', 'totalDevices', 'onlineDevices', 'recentEvents', 'latestScans' )); } // --- Globale Suche --- public function search(Request $request): View { $q = trim($request->get('q', '')); $devices = collect(); if (strlen($q) >= 2) { $devices = NetworkDevice::with('events') ->where(function ($query) use ($q) { $query->where('current_ip', 'like', "%{$q}%") ->orWhere('mac_address', 'like', "%{$q}%") ->orWhere('hostname', 'like', "%{$q}%") ->orWhere('label', 'like', "%{$q}%") ->orWhere('mac_vendor', 'like', "%{$q}%"); }) ->orderBy('current_ip') ->paginate(50) ->withQueryString(); } return view('network.search', compact('q', 'devices')); } // --- Alte index-Route umleiten --- public function index(): \Illuminate\Http\RedirectResponse { return redirect()->route('network.dashboard'); } // --- Alle Geräte --- public function devices(Request $request): View { $query = NetworkDevice::with('events') ->orderBy('current_ip'); if ($request->filled('status')) { $query->where('status', $request->status); } if ($request->filled('search')) { $s = $request->search; $query->where(function ($q) use ($s) { $q->where('current_ip', 'like', "%{$s}%") ->orWhere('mac_address', 'like', "%{$s}%") ->orWhere('hostname', 'like', "%{$s}%") ->orWhere('label', 'like', "%{$s}%") ->orWhere('mac_vendor', 'like', "%{$s}%"); }); } $devices = $query->paginate(50)->withQueryString(); return view('network.devices', compact('devices')); } // --- Geräte-Detail --- public function device(NetworkDevice $device): View { $device->load(['events.documentedBy', 'hosts.scan']); $ipHistory = $device->hosts() ->select('ip_address', 'status', 'ping_ms', 'created_at') ->join('network_scans', 'network_scans.id', '=', 'network_hosts.scan_id') ->orderByDesc('network_hosts.created_at') ->take(50) ->get(); return view('network.device', compact('device', 'ipHistory')); } // --- Gerät: Label/Notiz speichern --- public function updateDevice(Request $request, NetworkDevice $device): RedirectResponse { $validated = $request->validate([ 'label' => ['nullable', 'string', 'max:100'], 'notes' => ['nullable', 'string', 'max:1000'], ]); $oldLabel = $device->label; $device->update($validated); if ($oldLabel !== $validated['label']) { NetworkDeviceEvent::create([ 'device_id' => $device->id, 'event_type' => 'label_changed', 'old_value' => $oldLabel, 'new_value' => $validated['label'], 'description'=> 'Bezeichnung manuell geändert', 'documented' => true, 'documented_by' => auth()->id(), 'documented_at' => now(), ]); } return redirect()->route('network.device', $device) ->with('success', 'Gerät aktualisiert.'); } // --- Ereignis dokumentieren --- public function documentEvent(Request $request, NetworkDeviceEvent $event): RedirectResponse { $request->validate([ 'description' => ['nullable', 'string', 'max:500'], ]); $event->update([ 'documented' => true, 'documented_by' => auth()->id(), 'documented_at' => now(), 'description' => $request->description ?? $event->description, ]); return back()->with('success', 'Ereignis dokumentiert.'); } // --- Manuelle Notiz hinzufügen --- public function addNote(Request $request, NetworkDevice $device): RedirectResponse { $request->validate([ 'description' => ['required', 'string', 'max:500'], ]); NetworkDeviceEvent::create([ 'device_id' => $device->id, 'event_type' => 'manual_note', 'description' => $request->description, 'documented' => true, 'documented_by' => auth()->id(), 'documented_at' => now(), ]); return back()->with('success', 'Notiz hinzugefügt.'); } // --- Import --- public function showImport(): View { $segments = NetworkSegment::where('active', true)->orderBy('name')->get(); return view('network.import', compact('segments')); } public function import(Request $request, NetworkScanImporter $importer): RedirectResponse { $request->validate([ 'segment_id' => ['nullable', 'exists:network_segments,id'], 'scan_file' => ['required', 'file', 'mimes:txt,csv', 'max:10240'], ]); $path = $request->file('scan_file')->store('imports', 'local'); $fullPath = Storage::disk('local')->path($path); $scan = $importer->importAngryIpScannerFile( $fullPath, auth()->id(), $request->input('segment_id') ); return redirect()->route('network.scan', $scan) ->with('success', "Import abgeschlossen: {$scan->online_hosts} online, {$scan->new_devices} neue Geräte."); } // --- Scan-Detail --- public function scan(NetworkScan $scan): View { $hosts = $scan->hosts() ->orderByRaw("INET_ATON(ip_address)") ->get(); return view('network.scan', compact('scan', 'hosts')); } }