feat: Implementiere umfassende RESTful API für LLM Gateway
Fügt 21 neue API-Endpoints in 4 Phasen hinzu:
Phase 1 - Foundation (Provider & Models):
- GET /api/providers - Liste aller Provider
- GET /api/providers/{provider} - Provider-Details
- GET /api/models - Liste aller Models mit Filtering/Sorting
- GET /api/models/{provider}/{model} - Model-Details
Phase 2 - Core Features (Credentials, Budget, Pricing):
- GET/POST/PUT/DELETE /api/credentials - Credential-Management
- POST /api/credentials/{id}/test - Connection Testing
- GET /api/budget - Budget-Status mit Projektionen
- GET /api/budget/history - Budget-Historie
- GET /api/pricing - Model-Pricing-Listen
- GET /api/pricing/calculator - Kosten-Kalkulator
- GET /api/pricing/compare - Preis-Vergleich
Phase 3 - Analytics (Usage Statistics):
- GET /api/usage/summary - Umfassende Statistiken
- GET /api/usage/requests - Request-History mit Pagination
- GET /api/usage/requests/{id} - Request-Details
- GET /api/usage/charts - Chart-Daten (4 Typen)
Phase 4 - Account (Account Info & Activity):
- GET /api/account - User-Informationen
- GET /api/account/activity - Activity-Log
Features:
- Vollständige Scramble/Swagger-Dokumentation
- Consistent Error-Handling
- API-Key Authentication
- Filtering, Sorting, Pagination
- Budget-Tracking mit Alerts
- Provider-Breakdown
- Performance-Metriken
- Chart-Ready-Data
Controller erstellt:
- ProviderController
- ModelController
- CredentialController
- BudgetController
- PricingController
- UsageController
- AccountController
Dokumentation:
- API_KONZEPT.md - Vollständiges API-Konzept
- API_IMPLEMENTATION_STATUS.txt - Implementation-Tracking
- API_IMPLEMENTATION_SUMMARY.md - Zusammenfassung und Workflows
This commit is contained in:
255
laravel-app/app/Http/Controllers/Api/AccountController.php
Normal file
255
laravel-app/app/Http/Controllers/Api/AccountController.php
Normal file
@@ -0,0 +1,255 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\{GatewayUser, ApiKey, GatewayUserCredential, Budget, LlmRequest};
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class AccountController extends Controller
|
||||
{
|
||||
/**
|
||||
* Get account information
|
||||
*
|
||||
* Returns comprehensive information about the authenticated gateway user,
|
||||
* including API keys, provider configuration, budget, and statistics.
|
||||
*
|
||||
* ## Example Response
|
||||
*
|
||||
* ```json
|
||||
* {
|
||||
* "data": {
|
||||
* "user_id": "usr_xyz789",
|
||||
* "name": "API Client App",
|
||||
* "email": "api@example.com",
|
||||
* "status": "active",
|
||||
* "created_at": "2025-11-01T08:00:00Z",
|
||||
* "last_login": "2025-11-19T11:45:00Z",
|
||||
* "api_keys": [...],
|
||||
* "providers_configured": 3,
|
||||
* "budget": {...},
|
||||
* "statistics": {...},
|
||||
* "rate_limits": {...}
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @tags Account
|
||||
*
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function index(Request $request): JsonResponse
|
||||
{
|
||||
$user = $request->user();
|
||||
|
||||
// Get API keys
|
||||
$apiKeys = ApiKey::where('gateway_user_id', $user->user_id)
|
||||
->orderByDesc('created_at')
|
||||
->get()
|
||||
->map(function ($key) {
|
||||
return [
|
||||
'id' => $key->id,
|
||||
'name' => $key->name ?? 'Default Key',
|
||||
'key_preview' => substr($key->api_key, 0, 8) . '...' . substr($key->api_key, -4),
|
||||
'created_at' => $key->created_at->toIso8601String(),
|
||||
'last_used' => $key->last_used_at?->toIso8601String(),
|
||||
'expires_at' => $key->expires_at?->toIso8601String(),
|
||||
];
|
||||
});
|
||||
|
||||
// Count configured providers
|
||||
$providersConfigured = GatewayUserCredential::where('gateway_user_id', $user->user_id)
|
||||
->where('is_active', true)
|
||||
->count();
|
||||
|
||||
// Get budget info
|
||||
$budget = Budget::where('gateway_user_id', $user->user_id)->first();
|
||||
$monthlySpending = LlmRequest::where('gateway_user_id', $user->user_id)
|
||||
->whereYear('created_at', now()->year)
|
||||
->whereMonth('created_at', now()->month)
|
||||
->where('status', 'success')
|
||||
->sum('total_cost') ?? 0;
|
||||
|
||||
$budgetInfo = $budget ? [
|
||||
'total' => round($budget->monthly_limit, 2),
|
||||
'used' => round($monthlySpending, 4),
|
||||
'remaining' => round($budget->monthly_limit - $monthlySpending, 4),
|
||||
'currency' => 'USD',
|
||||
] : null;
|
||||
|
||||
// Get statistics
|
||||
$stats = LlmRequest::where('gateway_user_id', $user->user_id)
|
||||
->where('status', 'success')
|
||||
->selectRaw('
|
||||
COUNT(*) as total_requests,
|
||||
SUM(total_tokens) as total_tokens,
|
||||
SUM(total_cost) as total_cost,
|
||||
MIN(created_at) as first_request
|
||||
')
|
||||
->first();
|
||||
|
||||
return response()->json([
|
||||
'data' => [
|
||||
'user_id' => $user->user_id,
|
||||
'name' => $user->name,
|
||||
'email' => $user->email,
|
||||
'status' => $user->is_active ? 'active' : 'inactive',
|
||||
'created_at' => $user->created_at->toIso8601String(),
|
||||
'last_login' => $user->last_login_at?->toIso8601String(),
|
||||
'api_keys' => $apiKeys,
|
||||
'providers_configured' => $providersConfigured,
|
||||
'budget' => $budgetInfo,
|
||||
'statistics' => [
|
||||
'total_requests' => $stats->total_requests ?? 0,
|
||||
'total_tokens' => $stats->total_tokens ?? 0,
|
||||
'total_cost' => round($stats->total_cost ?? 0, 4),
|
||||
'first_request' => $stats->first_request?->toIso8601String(),
|
||||
],
|
||||
'rate_limits' => [
|
||||
'requests_per_minute' => 100, // TODO: Get from rate_limits table
|
||||
'tokens_per_request' => 10000,
|
||||
'daily_budget_limit' => $budget ? round($budget->monthly_limit / 30, 2) : null,
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get recent activity log
|
||||
*
|
||||
* Returns recent activity including requests, credential changes,
|
||||
* budget alerts, and other account events.
|
||||
*
|
||||
* ## Query Parameters
|
||||
*
|
||||
* - `limit` (optional) - Number of items (default: 20, max: 100)
|
||||
* - `type` (optional) - Activity type: request, credential_change, budget_alert, all (default: all)
|
||||
*
|
||||
* ## Example Response
|
||||
*
|
||||
* ```json
|
||||
* {
|
||||
* "data": [
|
||||
* {
|
||||
* "id": 1,
|
||||
* "type": "request",
|
||||
* "action": "chat_completion",
|
||||
* "details": {
|
||||
* "provider": "openai",
|
||||
* "model": "gpt-4-turbo",
|
||||
* "cost": 0.00405,
|
||||
* "status": "success"
|
||||
* },
|
||||
* "timestamp": "2025-11-19T11:45:00Z"
|
||||
* }
|
||||
* ],
|
||||
* "meta": {
|
||||
* "total": 156,
|
||||
* "limit": 20,
|
||||
* "has_more": true
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @tags Account
|
||||
*
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function activity(Request $request): JsonResponse
|
||||
{
|
||||
$validator = Validator::make($request->all(), [
|
||||
'limit' => 'sometimes|integer|min:1|max:100',
|
||||
'type' => 'sometimes|string|in:request,credential_change,budget_alert,all',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json([
|
||||
'error' => [
|
||||
'code' => 'validation_error',
|
||||
'message' => 'Invalid query parameters',
|
||||
'status' => 422,
|
||||
'details' => $validator->errors(),
|
||||
],
|
||||
], 422);
|
||||
}
|
||||
|
||||
$user = $request->user();
|
||||
$limit = $request->input('limit', 20);
|
||||
$type = $request->input('type', 'all');
|
||||
|
||||
$activities = collect();
|
||||
|
||||
// Get recent requests
|
||||
if ($type === 'all' || $type === 'request') {
|
||||
$recentRequests = LlmRequest::where('gateway_user_id', $user->user_id)
|
||||
->orderByDesc('created_at')
|
||||
->limit($limit)
|
||||
->get()
|
||||
->map(function ($req) {
|
||||
return [
|
||||
'id' => $req->id,
|
||||
'type' => 'request',
|
||||
'action' => 'chat_completion',
|
||||
'details' => [
|
||||
'provider' => $req->provider,
|
||||
'model' => $req->model,
|
||||
'cost' => round($req->total_cost, 6),
|
||||
'status' => $req->status,
|
||||
],
|
||||
'timestamp' => $req->created_at->toIso8601String(),
|
||||
'sort_timestamp' => $req->created_at,
|
||||
];
|
||||
});
|
||||
|
||||
$activities = $activities->merge($recentRequests);
|
||||
}
|
||||
|
||||
// Get credential changes
|
||||
if ($type === 'all' || $type === 'credential_change') {
|
||||
$credentialChanges = GatewayUserCredential::where('gateway_user_id', $user->user_id)
|
||||
->orderByDesc('created_at')
|
||||
->limit($limit)
|
||||
->get()
|
||||
->map(function ($cred) {
|
||||
return [
|
||||
'id' => $cred->id,
|
||||
'type' => 'credential_change',
|
||||
'action' => 'credentials_updated',
|
||||
'details' => [
|
||||
'provider' => $cred->provider,
|
||||
'status' => $cred->is_active ? 'active' : 'inactive',
|
||||
],
|
||||
'timestamp' => $cred->updated_at->toIso8601String(),
|
||||
'sort_timestamp' => $cred->updated_at,
|
||||
];
|
||||
});
|
||||
|
||||
$activities = $activities->merge($credentialChanges);
|
||||
}
|
||||
|
||||
// Sort by timestamp and limit
|
||||
$activities = $activities->sortByDesc('sort_timestamp')
|
||||
->take($limit)
|
||||
->values()
|
||||
->map(function ($activity) {
|
||||
unset($activity['sort_timestamp']);
|
||||
return $activity;
|
||||
});
|
||||
|
||||
// Count total activities (approximate)
|
||||
$totalCount = LlmRequest::where('gateway_user_id', $user->user_id)->count();
|
||||
|
||||
return response()->json([
|
||||
'data' => $activities,
|
||||
'meta' => [
|
||||
'total' => $totalCount,
|
||||
'limit' => $limit,
|
||||
'has_more' => $totalCount > $limit,
|
||||
],
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user