Files
laravel-llm-gateway/laravel-app/app/Http/Controllers/Api/AccountController.php
wtrinkl cb495e18e3 Fix API controllers to use correct database column names
- Fix model_pricing table references (model_id -> model, display_name -> model)
- Fix price columns (output_price_per_1k -> output_price_per_million)
- Add price conversion (per_million / 1000 = per_1k) in all API responses
- Add whereNotNull('model') filters to exclude invalid entries
- Add getModelDisplayName() helper method to all controllers
- Fix AccountController to use gateway_users budget fields directly
- Remove Budget model dependencies from AccountController
- Add custom Scramble server URL configuration for API docs
- Create ScrambleServiceProvider to set correct /api prefix
- Add migration to rename user_id to gateway_user_id in llm_requests
- Add custom ApiGuard for gateway_users authentication
- Update all API controllers: AccountController, ModelController, PricingController, ProviderController

All API endpoints now working correctly:
- GET /api/account
- GET /api/models
- GET /api/pricing
- GET /api/providers/{provider}
2025-11-19 19:36:58 +01:00

254 lines
8.8 KiB
PHP

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\{GatewayUser, ApiKey, GatewayUserCredential, 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 [
'token_preview' => substr($key->token, 0, 8) . '...' . substr($key->token, -4),
'name' => $key->key_name ?? $key->key_alias ?? 'Default Key',
'alias' => $key->key_alias,
'created_at' => $key->created_at->toIso8601String(),
'expires_at' => $key->expires?->toIso8601String(),
];
});
// Count configured providers
$providersConfigured = GatewayUserCredential::where('gateway_user_id', $user->user_id)
->where('is_active', true)
->count();
// Get budget info directly from gateway_user
// The gateway_users table has budget fields: monthly_budget_limit, current_month_spending
$budgetInfo = null;
if ($user->monthly_budget_limit !== null) {
$budgetInfo = [
'total' => round($user->monthly_budget_limit, 2),
'used' => round($user->current_month_spending, 4),
'remaining' => round($user->monthly_budget_limit - $user->current_month_spending, 4),
'currency' => 'USD',
'alert_threshold' => $user->budget_alert_threshold,
];
}
// 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' => $user->monthly_budget_limit ? round($user->monthly_budget_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,
],
]);
}
}