app->singleton(UploadDraftServiceInterface::class, function ($app) { return new UploadDraftService($app->make('filesystem')); }); } /** * Bootstrap any application services. */ public function boot(): void { $this->configureAuthRateLimiters(); $this->configureUploadRateLimiters(); $this->configureMailFailureLogging(); // Provide toolbar counts and user info to layout views (port of legacy toolbar logic) View::composer(['layouts.nova', 'layouts.nova.*'], function ($view) { $uploadCount = $favCount = $msgCount = $noticeCount = 0; $avatarHash = null; $displayName = null; $userId = null; if (Auth::check()) { $userId = Auth::id(); try { $uploadCount = DB::table('artworks')->where('user_id', $userId)->count(); } catch (\Throwable $e) { $uploadCount = 0; } try { // legacy table name fallback handled elsewhere; here we look for user_favorites or favourites $favCount = DB::table('user_favorites')->where('user_id', $userId)->count(); } catch (\Throwable $e) { try { $favCount = DB::table('favourites')->where('user_id', $userId)->count(); } catch (\Throwable $e) { $favCount = 0; } } try { $msgCount = DB::table('messages')->where('reciever_id', $userId)->whereNull('read_at')->count(); } catch (\Throwable $e) { $msgCount = 0; } try { $noticeCount = DB::table('notification')->where('user_id', $userId)->where('new', 1)->count(); } catch (\Throwable $e) { $noticeCount = 0; } try { $profile = DB::table('user_profiles')->where('user_id', $userId)->first(); $avatarHash = $profile->avatar_hash ?? null; } catch (\Throwable $e) { $avatarHash = null; } $displayName = Auth::user()->name ?: (Auth::user()->username ?? ''); } $view->with(compact('userId','uploadCount', 'favCount', 'msgCount', 'noticeCount', 'avatarHash', 'displayName')); }); } private function configureAuthRateLimiters(): void { RateLimiter::for('register-ip', function (Request $request): Limit { $limit = max(1, (int) config('registration.ip_per_minute_limit', 3)); return Limit::perMinute($limit)->by('register:ip:' . $request->ip()); }); RateLimiter::for('register-ip-daily', function (Request $request): Limit { $limit = max(1, (int) config('registration.ip_per_day_limit', 20)); return Limit::perDay($limit)->by('register:ip:daily:' . $request->ip()); }); RateLimiter::for('register', function (Request $request): array { $emailKey = strtolower((string) $request->input('email', 'unknown')); $ipLimit = (int) config('registration.ip_per_minute_limit', 3); $emailLimit = (int) config('registration.email_per_minute_limit', 6); return [ Limit::perMinute($ipLimit)->by('register:ip:' . $request->ip()), Limit::perMinute($emailLimit)->by('register:email:' . $emailKey), ]; }); } private function configureMailFailureLogging(): void { Event::listen(JobFailed::class, function (JobFailed $event): void { if (! str_contains(strtolower($event->job->resolveName()), 'sendqueuedmailable')) { return; } Log::warning('mail delivery failed', [ 'transport' => config('mail.default'), 'job_name' => $event->job->resolveName(), 'queue' => $event->job->getQueue(), 'connection' => $event->connectionName, 'exception' => $event->exception->getMessage(), ]); }); } private function configureUploadRateLimiters(): void { RateLimiter::for('uploads-init', function (Request $request): array { return $this->buildUploadLimits($request, 'init'); }); RateLimiter::for('uploads-finish', function (Request $request): array { return $this->buildUploadLimits($request, 'finish'); }); RateLimiter::for('uploads-status', function (Request $request): array { return $this->buildUploadLimits($request, 'status'); }); } private function buildUploadLimits(Request $request, string $key): array { $config = (array) config('uploads.rate_limits.' . $key, []); $decay = (int) config('uploads.rate_limits.decay_minutes', 1); $perUser = (int) ($config['per_user'] ?? 0); $perIp = (int) ($config['per_ip'] ?? 0); $limits = []; if ($perUser > 0) { $userId = $request->user()?->id ?? 'guest'; $limits[] = Limit::perMinutes($decay, $perUser)->by('u:' . $userId); } if ($perIp > 0) { $limits[] = Limit::perMinutes($decay, $perIp)->by('ip:' . $request->ip()); } return $limits; } }