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
256 lines
8.8 KiB
PHP
256 lines
8.8 KiB
PHP
<?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,
|
|
],
|
|
]);
|
|
}
|
|
}
|