Initial commit: Any-LLM Gateway with Laravel Admin Interface
- Any-LLM Gateway setup with Docker Compose - Laravel 11 admin interface with Livewire - Dashboard with usage statistics and charts - Gateway Users management with budget tracking - API Keys management with revocation - Budget templates with assignment - Usage Logs with filtering and CSV export - Model Pricing management with calculator - PostgreSQL database integration - Complete authentication system for admins
This commit is contained in:
242
laravel-app/app/Http/Controllers/GatewayUserController.php
Normal file
242
laravel-app/app/Http/Controllers/GatewayUserController.php
Normal file
@@ -0,0 +1,242 @@
|
||||
<?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::with('budget')
|
||||
->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', 'budget'])
|
||||
->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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user