diff --git a/laravel-app/app/Http/Controllers/DashboardController.php b/laravel-app/app/Http/Controllers/DashboardController.php index 30cca09..e50ee66 100644 --- a/laravel-app/app/Http/Controllers/DashboardController.php +++ b/laravel-app/app/Http/Controllers/DashboardController.php @@ -18,20 +18,12 @@ class DashboardController extends Controller { $stats = $this->statsService->getDashboardStats(); $dailyUsage = $this->statsService->getDailyUsageChart(30); - $topUsers = $this->statsService->getTopUsers(5); $providerStats = $this->statsService->getUsageByProvider(30); - $modelStats = $this->statsService->getUsageByModel(30); - $costTrends = $this->statsService->getCostTrends(30); - $errorStats = $this->statsService->getErrorStats(30); return view('dashboard', compact( 'stats', 'dailyUsage', - 'topUsers', - 'providerStats', - 'modelStats', - 'costTrends', - 'errorStats' + 'providerStats' )); } diff --git a/laravel-app/app/Models/GatewayUser.php b/laravel-app/app/Models/GatewayUser.php index 34edb0c..b5c344e 100644 --- a/laravel-app/app/Models/GatewayUser.php +++ b/laravel-app/app/Models/GatewayUser.php @@ -52,6 +52,11 @@ class GatewayUser extends Model implements Authenticatable return $this->hasMany(UsageLog::class, 'gateway_user_id', 'user_id'); } + public function llmRequests() + { + return $this->hasMany(LlmRequest::class, 'gateway_user_id', 'user_id'); + } + // Scopes public function scopeActive($query) { diff --git a/laravel-app/app/Models/LlmRequest.php b/laravel-app/app/Models/LlmRequest.php index a494ba6..343097b 100644 --- a/laravel-app/app/Models/LlmRequest.php +++ b/laravel-app/app/Models/LlmRequest.php @@ -8,7 +8,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; class LlmRequest extends Model { protected $fillable = [ - 'user_id', + 'gateway_user_id', 'provider', 'model', 'request_payload', @@ -41,9 +41,9 @@ class LlmRequest extends Model 'http_status' => 'integer', ]; - public function user(): BelongsTo + public function gatewayUser(): BelongsTo { - return $this->belongsTo(User::class); + return $this->belongsTo(GatewayUser::class, 'gateway_user_id', 'user_id'); } public function isSuccess(): bool diff --git a/laravel-app/app/Models/User.php b/laravel-app/app/Models/User.php index 541cebc..273c2f9 100644 --- a/laravel-app/app/Models/User.php +++ b/laravel-app/app/Models/User.php @@ -69,12 +69,4 @@ class User extends Authenticatable { return $this->hasMany(UserProviderCredential::class); } - - /** - * Get the user's LLM requests - */ - public function llmRequests() - { - return $this->hasMany(LlmRequest::class); - } } diff --git a/laravel-app/app/Services/StatisticsService.php b/laravel-app/app/Services/StatisticsService.php index 2841c78..7b610a2 100644 --- a/laravel-app/app/Services/StatisticsService.php +++ b/laravel-app/app/Services/StatisticsService.php @@ -3,7 +3,7 @@ namespace App\Services; use App\Models\LlmRequest; -use App\Models\User; +use App\Models\GatewayUser; use App\Models\UserProviderCredential; use Illuminate\Support\Facades\DB; @@ -15,8 +15,9 @@ class StatisticsService public function getDashboardStats(): array { return [ - 'total_users' => User::count(), - 'active_credentials' => UserProviderCredential::where('is_active', true)->count(), + 'total_gateway_users' => GatewayUser::count(), + 'active_gateway_users' => GatewayUser::where('blocked', false)->count(), + 'blocked_gateway_users' => GatewayUser::where('blocked', true)->count(), 'total_requests_today' => LlmRequest::whereDate('created_at', today())->count(), 'total_spend_today' => LlmRequest::whereDate('created_at', today())->sum('total_cost') ?? 0, 'total_tokens_today' => LlmRequest::whereDate('created_at', today())->sum('total_tokens') ?? 0, @@ -73,11 +74,11 @@ class StatisticsService } /** - * Get top users by spend + * Get top gateway users by spend */ public function getTopUsers(int $limit = 10) { - return User::select('users.*') + return GatewayUser::select('gateway_users.*') ->withCount('llmRequests') ->withSum('llmRequests as total_cost', 'total_cost') ->withSum('llmRequests as total_tokens', 'total_tokens') @@ -91,18 +92,18 @@ class StatisticsService */ public function getRecentActivity(int $limit = 20) { - return LlmRequest::with('user') + return LlmRequest::with('gatewayUser') ->orderByDesc('created_at') ->limit($limit) ->get(); } /** - * Get user statistics + * Get gateway user statistics */ - public function getUserStatistics(int $userId, int $days = 30) + public function getGatewayUserStatistics(string $gatewayUserId, int $days = 30) { - return LlmRequest::where('user_id', $userId) + return LlmRequest::where('gateway_user_id', $gatewayUserId) ->where('created_at', '>=', now()->subDays($days)) ->where('status', 'success') ->selectRaw(' diff --git a/laravel-app/resources/views/budgets/create.blade.php b/laravel-app/resources/views/budgets/create.blade.php deleted file mode 100644 index 0db825d..0000000 --- a/laravel-app/resources/views/budgets/create.blade.php +++ /dev/null @@ -1,113 +0,0 @@ - - -

- Create Budget Template -

-
- -
-
-
-
-
- @csrf - - -
- - - @error('budget_name') -

{{ $message }}

- @enderror -
- - -
- - - @error('max_budget') -

{{ $message }}

- @enderror -
- - -
- - - @error('budget_type') -

{{ $message }}

- @enderror -
- - - - - -
-

ℹ️ Budget Template Info

-
    -
  • • Budget templates can be assigned to multiple users
  • -
  • • Users will automatically reset when duration expires
  • -
  • • "Unlimited" budgets never reset automatically
  • -
-
- - -
- Cancel - -
-
-
-
-
-
- - @push('scripts') - - @endpush -
diff --git a/laravel-app/resources/views/budgets/edit.blade.php b/laravel-app/resources/views/budgets/edit.blade.php deleted file mode 100644 index ba9fc58..0000000 --- a/laravel-app/resources/views/budgets/edit.blade.php +++ /dev/null @@ -1,102 +0,0 @@ - - -

- Edit Budget Template -

-
- -
-
-
-
-
- @csrf - @method('PUT') - - -
- - -
- - -
- - - @error('max_budget') -

{{ $message }}

- @enderror -
- - -
- - - @error('budget_type') -

{{ $message }}

- @enderror -
- - -
- - - @error('custom_duration_days') -

{{ $message }}

- @enderror -
- - -
-

⚠️ Warning

-

- This budget is currently assigned to {{ $budget->gatewayUsers()->count() }} user(s). - Changes will affect all assigned users. -

-
- - -
- Cancel - -
-
-
-
-
-
- - @push('scripts') - - @endpush -
diff --git a/laravel-app/resources/views/budgets/index.blade.php b/laravel-app/resources/views/budgets/index.blade.php deleted file mode 100644 index 4a75aba..0000000 --- a/laravel-app/resources/views/budgets/index.blade.php +++ /dev/null @@ -1,98 +0,0 @@ - - -
-

- Budget Templates -

- - Create Budget Template - -
-
- -
-
- @if(session('success')) -
- {{ session('success') }} -
- @endif - - @if(session('error')) -
- {{ session('error') }} -
- @endif - -
-
- @if($budgets->count() > 0) - - - - - - - - - - - - - @foreach($budgets as $budget) - - - - - - - - - @endforeach - -
- Budget ID - - Max Budget - - Duration - - Assigned Users - - Created - - Actions -
- {{ $budget->budget_id }} - - {{ $budget->max_budget_formatted }} - - {{ $budget->duration_human }} - - - {{ $budget->gateway_users_count }} users - - - {{ $budget->created_at->format('M d, Y') }} - - View - Edit -
- @csrf - @method('DELETE') - -
-
- -
- {{ $budgets->links() }} -
- @else -

No budget templates found. Create your first budget template to get started.

- @endif -
-
-
-
-
diff --git a/laravel-app/resources/views/budgets/show.blade.php b/laravel-app/resources/views/budgets/show.blade.php deleted file mode 100644 index ddb78b8..0000000 --- a/laravel-app/resources/views/budgets/show.blade.php +++ /dev/null @@ -1,164 +0,0 @@ - - -
-

- Budget Details -

-
- - Edit Budget - -
- @csrf - @method('DELETE') - -
-
-
-
- -
-
- @if(session('success')) -
- {{ session('success') }} -
- @endif - - -
-
-

Budget Information

-
-
-
Budget ID
-
{{ $budget->budget_id }}
-
-
-
Maximum Budget
-
{{ $budget->max_budget_formatted }}
-
-
-
Duration
-
{{ $budget->duration_human }}
-
-
-
Assigned Users
-
{{ $budget->gatewayUsers()->count() }}
-
-
-
Created
-
{{ $budget->created_at->format('M d, Y H:i') }}
-
-
-
Last Updated
-
{{ $budget->updated_at->format('M d, Y H:i') }}
-
-
-
-
- - -
-
-

Assigned Users ({{ $budget->gatewayUsers()->count() }})

- - @if($budget->gatewayUsers()->count() > 0) - - - - - - - - - - - - - @foreach($budget->gatewayUsers as $user) - - - - - - - - - @endforeach - -
User IDAliasCurrent SpendBudget StartedNext ResetActions
- {{ $user->user_id }} - - {{ $user->alias ?? '-' }} - - - {{ $user->spend_formatted }} - - / {{ $budget->max_budget_formatted }} - - {{ $user->budget_started_at?->format('M d, Y') ?? '-' }} - - {{ $user->next_budget_reset_at?->format('M d, Y') ?? 'Never' }} - - View -
- @else -

No users assigned to this budget yet.

- @endif -
-
- - - @if($availableUsers->count() > 0) -
-
-

Assign Users to Budget

- -
- @csrf - -
- -
- @foreach($availableUsers as $user) -
- - -
- @endforeach -
- @error('user_ids') -

{{ $message }}

- @enderror -
- -
- -
-
-
-
- @else -
-
- All users are currently assigned to budgets. No available users to assign. -
-
- @endif -
-
-
diff --git a/laravel-app/resources/views/dashboard.blade.php b/laravel-app/resources/views/dashboard.blade.php index 18ae2e3..907fbfa 100644 --- a/laravel-app/resources/views/dashboard.blade.php +++ b/laravel-app/resources/views/dashboard.blade.php @@ -10,17 +10,17 @@
- +
-

Total Users

+

Gateway Users

- {{ number_format($stats['total_users']) }} + {{ number_format($stats['total_gateway_users']) }}

-

- {{ $stats['active_credentials'] }} active credentials +

+ {{ $stats['active_gateway_users'] }} active

@@ -99,112 +99,58 @@
- +
-

- Usage Trend (Last 30 Days) -

- +

Daily Usage (Last 30 Days)

+
- -
- -
-
-

- Usage by Provider -

- -
-
- - -
-
-

- Top Users by Spend -

-
- @forelse($topUsers as $user) -
-
-

- {{ $user->name }} -

-

- {{ number_format($user->llm_requests_count ?? 0) }} requests -

-
-
-

- ${{ number_format($user->total_cost ?? 0, 2) }} -

-

- {{ number_format($user->total_tokens ?? 0) }} tokens -

-
-
- @empty -

- No usage data yet -

- @endforelse -
-
-
-
- - +
-

- Most Used Models -

+

Provider Statistics (Last 30 Days)

- - - - - + + + + - @forelse($modelStats as $model) + @forelse($providerStats as $provider) - - - - - @empty - @endforelse @@ -218,36 +164,34 @@ @push('scripts') - + @endpush diff --git a/laravel-app/resources/views/gateway-users/create.blade.php b/laravel-app/resources/views/gateway-users/create.blade.php index d304f91..e2ab3ae 100644 --- a/laravel-app/resources/views/gateway-users/create.blade.php +++ b/laravel-app/resources/views/gateway-users/create.blade.php @@ -35,28 +35,6 @@ @enderror - -
- - -

Assign a spending limit to this user

- @error('budget_id') -

{{ $message }}

- @enderror -
-
diff --git a/laravel-app/resources/views/gateway-users/edit.blade.php b/laravel-app/resources/views/gateway-users/edit.blade.php index e2abb37..2006848 100644 --- a/laravel-app/resources/views/gateway-users/edit.blade.php +++ b/laravel-app/resources/views/gateway-users/edit.blade.php @@ -47,28 +47,6 @@ @enderror
- -
- - - @error('budget_id') -

{{ $message }}

- @enderror -
-
ModelProviderRequestsTokensCost + Provider + + Requests + + Total Cost + + Total Tokens +
- {{ $model->model }} - - - {{ ucfirst($model->provider) }} + + + {{ $provider->provider }} - {{ number_format($model->count) }} + + {{ number_format($provider->count) }} - {{ number_format($model->tokens ?? 0) }} + + ${{ number_format($provider->total_cost, 2) }} - ${{ number_format($model->total_cost ?? 0, 4) }} + + {{ number_format($provider->total_tokens) }}
- No usage data yet + + No data available yet
diff --git a/laravel-app/resources/views/keys/show.blade.php b/laravel-app/resources/views/keys/show.blade.php index f0155d1..8363677 100644 --- a/laravel-app/resources/views/keys/show.blade.php +++ b/laravel-app/resources/views/keys/show.blade.php @@ -56,10 +56,14 @@
Associated User
- - {{ $apiKey->gatewayUser->alias ?? $apiKey->user_id }} - + @if($apiKey->user_id) + + {{ $apiKey->gatewayUser->alias ?? $apiKey->user_id }} + + @else + No user assigned + @endif
diff --git a/laravel-app/resources/views/livewire/layout/navigation.blade.php b/laravel-app/resources/views/livewire/layout/navigation.blade.php index e558994..4c1b535 100644 --- a/laravel-app/resources/views/livewire/layout/navigation.blade.php +++ b/laravel-app/resources/views/livewire/layout/navigation.blade.php @@ -39,9 +39,6 @@ new class extends Component {{ __('API Keys') }} - - {{ __('Budgets') }} - {{ __('Usage Logs') }} @@ -51,9 +48,6 @@ new class extends Component {{ __('Credentials') }} - - {{ __('User Budgets') }} - @@ -111,9 +105,6 @@ new class extends Component {{ __('API Keys') }} - - {{ __('Budgets') }} - {{ __('Usage Logs') }} @@ -123,9 +114,6 @@ new class extends Component {{ __('Credentials') }} - - {{ __('User Budgets') }} - diff --git a/laravel-app/routes/web.php b/laravel-app/routes/web.php index 3d01b03..e6c5444 100644 --- a/laravel-app/routes/web.php +++ b/laravel-app/routes/web.php @@ -4,12 +4,9 @@ use Illuminate\Support\Facades\Route; use App\Http\Controllers\DashboardController; use App\Http\Controllers\GatewayUserController; use App\Http\Controllers\ApiKeyController; -use App\Http\Controllers\BudgetController; use App\Http\Controllers\UsageLogController; use App\Http\Controllers\ModelPricingController; use App\Http\Controllers\Admin\CredentialController; -use App\Http\Controllers\Admin\UserBudgetController; -use App\Http\Controllers\Admin\UserManagementController; Route::view('/', 'welcome'); @@ -30,11 +27,6 @@ Route::middleware(['auth', 'verified'])->group(function () { Route::post('keys/{id}/revoke', [ApiKeyController::class, 'revoke']) ->name('keys.revoke'); - // Budgets Management - Route::resource('budgets', BudgetController::class); - Route::post('budgets/{id}/assign-users', [BudgetController::class, 'assignUsers']) - ->name('budgets.assign-users'); - // Usage Logs Route::get('usage-logs', [UsageLogController::class, 'index'])->name('usage-logs.index'); Route::get('usage-logs/export', [UsageLogController::class, 'export'])->name('usage-logs.export'); @@ -49,28 +41,12 @@ Route::middleware(['auth', 'verified'])->group(function () { // Provider Credentials Management (Admin) Route::prefix('admin')->name('admin.')->group(function () { - // User Management - Route::get('users', [UserManagementController::class, 'index']) - ->name('users.index'); - // Credentials Route::resource('credentials', CredentialController::class); Route::post('credentials/{credential}/test', [CredentialController::class, 'test']) ->name('credentials.test'); Route::post('credentials/{credential}/toggle', [CredentialController::class, 'toggle']) ->name('credentials.toggle'); - - // User Budget & Rate Limit Management - Route::get('users/{user}/budget', [UserBudgetController::class, 'show']) - ->name('users.budget.show'); - Route::put('users/{user}/budget', [UserBudgetController::class, 'updateBudget']) - ->name('users.budget.update'); - Route::put('users/{user}/rate-limit', [UserBudgetController::class, 'updateRateLimit']) - ->name('users.rate-limit.update'); - Route::post('users/{user}/rate-limit/reset', [UserBudgetController::class, 'resetRateLimit']) - ->name('users.rate-limit.reset'); - Route::post('users/{user}/budget/reset', [UserBudgetController::class, 'resetBudget']) - ->name('users.budget.reset'); }); });