Files
laravel-llm-gateway/laravel-app/app/Http/Controllers/GatewayUserController.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

242 lines
7.2 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\GatewayUser;
use App\Models\Budget;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class GatewayUserController extends Controller
{
/**
* Display a listing of the gateway users.
*/
public function index(Request $request)
{
$query = GatewayUser::withCount(['apiKeys', 'usageLogs']);
// Search
if ($request->filled('search')) {
$search = $request->search;
$query->where(function ($q) use ($search) {
$q->where('user_id', 'like', "%{$search}%")
->orWhere('alias', 'like', "%{$search}%");
});
}
// Filter by status
if ($request->filled('status')) {
if ($request->status === 'active') {
$query->active();
} elseif ($request->status === 'blocked') {
$query->blocked();
}
}
// Sort
$sortField = $request->get('sort', 'created_at');
$sortDirection = $request->get('direction', 'desc');
$query->orderBy($sortField, $sortDirection);
$users = $query->paginate(20)->withQueryString();
return view('gateway-users.index', compact('users'));
}
/**
* Show the form for creating a new gateway user.
*/
public function create()
{
$budgets = Budget::all();
return view('gateway-users.create', compact('budgets'));
}
/**
* Store a newly created gateway user in storage.
*/
public function store(Request $request)
{
$validated = $request->validate([
'alias' => 'nullable|string|max:255',
'budget_id' => 'nullable|exists:budgets,budget_id',
'metadata' => 'nullable|array',
]);
// Generate unique user_id
$userId = 'user_' . Str::random(16);
$user = GatewayUser::create([
'user_id' => $userId,
'alias' => $validated['alias'] ?? null,
'budget_id' => $validated['budget_id'] ?? null,
'spend' => 0,
'blocked' => false,
'metadata' => $validated['metadata'] ?? [],
]);
return redirect()
->route('gateway-users.show', $user->user_id)
->with('success', 'Gateway User created successfully!');
}
/**
* Display the specified gateway user.
*/
public function show(string $userId)
{
$user = GatewayUser::with(['apiKeys'])
->findOrFail($userId);
// Get usage statistics for last 30 days
$stats = $this->getUserStatistics($userId, 30);
// Get recent logs
$recentLogs = $user->usageLogs()
->with('apiKey')
->orderByDesc('timestamp')
->limit(50)
->get();
// Get daily usage for chart (last 30 days)
$dailyUsage = $user->usageLogs()
->selectRaw('DATE(timestamp) as date, COUNT(*) as requests, SUM(cost) as cost, SUM(total_tokens) as tokens')
->where('timestamp', '>=', now()->subDays(30))
->groupBy('date')
->orderBy('date')
->get();
return view('gateway-users.show', compact('user', 'stats', 'recentLogs', 'dailyUsage'));
}
/**
* Show the form for editing the specified gateway user.
*/
public function edit(string $userId)
{
$user = GatewayUser::findOrFail($userId);
$budgets = Budget::all();
return view('gateway-users.edit', compact('user', 'budgets'));
}
/**
* Update the specified gateway user in storage.
*/
public function update(Request $request, string $userId)
{
$user = GatewayUser::findOrFail($userId);
$validated = $request->validate([
'alias' => 'nullable|string|max:255',
'budget_id' => 'nullable|exists:budgets,budget_id',
'metadata' => 'nullable|array',
]);
$user->update($validated);
return redirect()
->route('gateway-users.show', $user->user_id)
->with('success', 'Gateway User updated successfully!');
}
/**
* Remove the specified gateway user from storage.
*/
public function destroy(string $userId)
{
$user = GatewayUser::findOrFail($userId);
// Delete associated API keys and usage logs
$user->apiKeys()->delete();
$user->usageLogs()->delete();
$user->delete();
return redirect()
->route('gateway-users.index')
->with('success', 'Gateway User deleted successfully!');
}
/**
* Toggle block status of a gateway user.
*/
public function toggleBlock(string $userId)
{
$user = GatewayUser::findOrFail($userId);
$user->blocked = !$user->blocked;
$user->save();
$status = $user->blocked ? 'blocked' : 'unblocked';
return redirect()
->back()
->with('success', "User has been {$status} successfully!");
}
/**
* Bulk actions for gateway users.
*/
public function bulkAction(Request $request)
{
$validated = $request->validate([
'action' => 'required|in:block,unblock,delete',
'user_ids' => 'required|array|min:1',
'user_ids.*' => 'exists:users,user_id',
]);
$count = 0;
switch ($validated['action']) {
case 'block':
GatewayUser::whereIn('user_id', $validated['user_ids'])
->update(['blocked' => true]);
$count = count($validated['user_ids']);
$message = "{$count} user(s) have been blocked successfully!";
break;
case 'unblock':
GatewayUser::whereIn('user_id', $validated['user_ids'])
->update(['blocked' => false]);
$count = count($validated['user_ids']);
$message = "{$count} user(s) have been unblocked successfully!";
break;
case 'delete':
foreach ($validated['user_ids'] as $userId) {
$user = GatewayUser::find($userId);
if ($user) {
$user->apiKeys()->delete();
$user->usageLogs()->delete();
$user->delete();
$count++;
}
}
$message = "{$count} user(s) have been deleted successfully!";
break;
}
return redirect()
->route('gateway-users.index')
->with('success', $message);
}
/**
* Get user statistics for a given time period.
*/
private function getUserStatistics(string $userId, int $days)
{
return \App\Models\UsageLog::where('user_id', $userId)
->where('timestamp', '>=', now()->subDays($days))
->selectRaw('
COUNT(*) as total_requests,
SUM(prompt_tokens) as total_prompt_tokens,
SUM(completion_tokens) as total_completion_tokens,
SUM(total_tokens) as total_tokens,
SUM(cost) as total_cost,
AVG(total_tokens) as avg_tokens_per_request
')
->first();
}
}