has('status')) { switch ($request->status) { case 'active': $query->active(); break; case 'expired': $query->expired(); break; case 'inactive': $query->where('is_active', false); break; } } // Filter by user if ($request->has('user_id') && $request->user_id) { $query->where('user_id', $request->user_id); } // Search by key name if ($request->has('search') && $request->search) { $query->where('key_name', 'like', '%' . $request->search . '%'); } // Sort $sortBy = $request->get('sort_by', 'created_at'); $sortOrder = $request->get('sort_order', 'desc'); $query->orderBy($sortBy, $sortOrder); $apiKeys = $query->paginate(20)->withQueryString(); $gatewayUsers = GatewayUser::orderBy('alias')->get(); return view('api-keys.index', compact('apiKeys', 'gatewayUsers')); } /** * Show the form for creating a new API key. */ public function create() { $gatewayUsers = GatewayUser::orderBy('alias')->get(); return view('api-keys.create', compact('gatewayUsers')); } /** * Store a newly created API key. */ public function store(Request $request) { $validated = $request->validate([ 'key_name' => 'required|string|max:255', 'user_id' => 'required|string|exists:users,user_id', 'expires_at' => 'nullable|date|after:now', 'metadata' => 'nullable|json', ]); try { // Get master key from config $masterKey = env('GATEWAY_MASTER_KEY'); if (!$masterKey) { return back()->with('error', 'Gateway Master Key not configured'); } // Prepare request payload $payload = [ 'user_id' => $validated['user_id'], 'key_name' => $validated['key_name'], ]; // Add optional fields only if they have values if (!empty($validated['expires_at'])) { $payload['expires_at'] = $validated['expires_at']; } if (!empty($validated['metadata'])) { $payload['metadata'] = json_decode($validated['metadata'], true) ?: new \stdClass(); } // Create Virtual Key via Any-LLM Gateway API $response = Http::withHeaders([ 'X-AnyLLM-Key' => 'Bearer ' . $masterKey, 'Content-Type' => 'application/json', ])->post(env('GATEWAY_API_URL', 'http://gateway:8000') . '/v1/keys', $payload); if (!$response->successful()) { Log::error('Failed to create API key', [ 'status' => $response->status(), 'body' => $response->body() ]); return back()->with('error', 'Failed to create API key: ' . $response->body()); } $data = $response->json(); // The actual key is only available once - store it in session for display session()->flash('new_api_key', $data['key'] ?? null); session()->flash('new_api_key_id', $data['id'] ?? null); return redirect()->route('api-keys.index') ->with('success', 'API Key created successfully! Make sure to copy it now - it won\'t be shown again.'); } catch (\Exception $e) { Log::error('Exception creating API key', ['error' => $e->getMessage()]); return back()->with('error', 'Failed to create API key: ' . $e->getMessage()); } } /** * Display the specified API key. */ public function show(string $id) { $apiKey = ApiKey::with(['gatewayUser', 'usageLogs'])->findOrFail($id); // Get usage statistics $stats = [ 'total_requests' => $apiKey->usageLogs()->count(), 'total_cost' => $apiKey->usageLogs()->sum('cost'), 'total_tokens' => $apiKey->usageLogs()->sum('total_tokens'), 'last_30_days_requests' => $apiKey->usageLogs() ->where('timestamp', '>=', now()->subDays(30)) ->count(), ]; // Get recent activity $recentLogs = $apiKey->usageLogs() ->orderByDesc('timestamp') ->limit(20) ->get(); return view('api-keys.show', compact('apiKey', 'stats', 'recentLogs')); } /** * Revoke the specified API key. */ public function revoke(string $id) { try { $apiKey = ApiKey::findOrFail($id); // Get master key from config $masterKey = env('GATEWAY_MASTER_KEY'); if (!$masterKey) { return back()->with('error', 'Gateway Master Key not configured'); } // Revoke via Any-LLM Gateway API $response = Http::withHeaders([ 'X-AnyLLM-Key' => 'Bearer ' . $masterKey, 'Content-Type' => 'application/json', ])->delete(env('GATEWAY_API_URL', 'http://gateway:8000') . '/v1/keys/' . $id); if (!$response->successful()) { Log::error('Failed to revoke API key', [ 'key_id' => $id, 'status' => $response->status(), 'body' => $response->body() ]); return back()->with('error', 'Failed to revoke API key: ' . $response->body()); } return redirect()->route('api-keys.index') ->with('success', 'API Key revoked successfully'); } catch (\Exception $e) { Log::error('Exception revoking API key', ['error' => $e->getMessage()]); return back()->with('error', 'Failed to revoke API key: ' . $e->getMessage()); } } /** * Remove the specified API key. */ public function destroy(string $id) { // This is an alias for revoke return $this->revoke($id); } }