orderBy('ip_address') ->get(); $unmappedIps = OperationLog::query() ->select( 'operation_logs.ip_address', DB::raw('COUNT(*) as logs_count'), DB::raw('MAX(operation_logs.created_at) as last_seen_at') ) ->leftJoin('ip_user_mappings', 'operation_logs.ip_address', '=', 'ip_user_mappings.ip_address') ->whereNull('ip_user_mappings.id') ->where('operation_logs.ip_address', '!=', '') ->groupBy('operation_logs.ip_address') ->orderByDesc('last_seen_at') ->get(); return response()->json([ 'success' => true, 'data' => [ 'mappings' => $mappings, 'unmapped_ips' => $unmappedIps, ], ]); } public function store(Request $request): JsonResponse { $data = $request->validate([ 'ip_address' => ['required', 'ip', 'max:64', 'unique:ip_user_mappings,ip_address'], 'user_name' => ['required', 'string', 'max:128'], 'remark' => ['nullable', 'string', 'max:255'], ]); $mapping = IpUserMapping::query()->create($data); return response()->json([ 'success' => true, 'data' => [ 'mapping' => $mapping, ], ]); } public function update(Request $request, IpUserMapping $mapping): JsonResponse { $data = $request->validate([ 'ip_address' => [ 'required', 'ip', 'max:64', Rule::unique('ip_user_mappings', 'ip_address')->ignore($mapping->id), ], 'user_name' => ['required', 'string', 'max:128'], 'remark' => ['nullable', 'string', 'max:255'], ]); $mapping->update($data); return response()->json([ 'success' => true, 'data' => [ 'mapping' => $mapping->refresh(), ], ]); } public function destroy(IpUserMapping $mapping): JsonResponse { $mapping->delete(); return response()->json([ 'success' => true, ]); } }