159 lines
5.6 KiB
PHP
159 lines
5.6 KiB
PHP
<?php
|
|
|
|
namespace App\Providers;
|
|
|
|
use Illuminate\Cache\RateLimiting\Limit;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\RateLimiter;
|
|
use Illuminate\Support\ServiceProvider;
|
|
use App\Services\Upload\Contracts\UploadDraftServiceInterface;
|
|
use App\Services\Upload\UploadDraftService;
|
|
use Illuminate\Support\Facades\View;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Event;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Queue\Events\JobFailed;
|
|
|
|
class AppServiceProvider extends ServiceProvider
|
|
{
|
|
/**
|
|
* Register any application services.
|
|
*/
|
|
public function register(): void
|
|
{
|
|
// Bind UploadDraftService interface to implementation
|
|
$this->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', function (Request $request): array {
|
|
$emailKey = strtolower((string) $request->input('email', 'unknown'));
|
|
$ipLimit = (int) config('antispam.register.ip_per_minute', 20);
|
|
$emailLimit = (int) config('antispam.register.email_per_minute', 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;
|
|
}
|
|
}
|