forge/app/Http/Controllers/ModVersionController.php
Refringe 7e1c66f250
Download Count Review
Reviewed the download count PR work and made some changes:
- Updated the download link route to include the mod's slug for easier identification.
- Moved rate limiter from the route middleware (the entire controller) to just the show method in the controller.
- Created a ModVersionPolicy that the controller can check against.
- Moves download increment logic into the model.
- Defers the call to the download increment logic (now run in the background)
- Updated the route to have a name, and the downloadUrl methods to build the URL dynamically using the route name.
- Wrote some tests to check URL building, download counting, and rate limiting.

# Conflicts:
#	app/Http/Controllers/ModVersionController.php
#	app/Providers/AppServiceProvider.php
2024-09-25 17:04:46 -04:00

43 lines
1.3 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Models\ModVersion;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
class ModVersionController extends Controller
{
use AuthorizesRequests;
public function show(Request $request, int $modId, string $slug, string $version): RedirectResponse
{
$modVersion = ModVersion::whereModId($modId)
->whereVersion($version)
->firstOrFail();
if ($modVersion->mod->slug !== $slug) {
abort(404);
}
$this->authorize('view', $modVersion);
// Rate limit the downloads.
$rateKey = 'mod-download:'.($request->user()?->id ?: $request->ip());
if (RateLimiter::tooManyAttempts($rateKey, maxAttempts: 5)) { // Max attempts is per minute.
abort(429);
}
// Increment downloads counts in the background.
defer(fn () => $modVersion->incrementDownloads());
// Increment the rate limiter.
RateLimiter::increment($rateKey);
// Redirect to the download link, using a 307 status code to prevent browsers from caching.
return redirect($modVersion->link, 307);
}
}