Files
SkinbaseNova/app/Http/Middleware/RedirectLegacyProfileSubdomain.php
2026-03-20 21:17:26 +01:00

107 lines
3.0 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Http\Middleware;
use App\Models\User;
use App\Support\UsernamePolicy;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Symfony\Component\HttpFoundation\Response;
class RedirectLegacyProfileSubdomain
{
public function handle(Request $request, Closure $next): Response
{
$canonicalUsername = $this->resolveCanonicalUsername($request);
if ($canonicalUsername !== null) {
return redirect()->to($this->targetUrl($request, $canonicalUsername), 301);
}
return $next($request);
}
private function resolveCanonicalUsername(Request $request): ?string
{
$configuredHost = parse_url((string) config('app.url'), PHP_URL_HOST);
if (! is_string($configuredHost) || $configuredHost === '') {
return null;
}
$requestHost = strtolower($request->getHost());
$configuredHost = strtolower($configuredHost);
if ($requestHost === $configuredHost || ! str_ends_with($requestHost, '.' . $configuredHost)) {
return null;
}
$subdomain = substr($requestHost, 0, -strlen('.' . $configuredHost));
if ($subdomain === '' || str_contains($subdomain, '.')) {
return null;
}
$candidate = UsernamePolicy::normalize($subdomain);
if ($candidate === '' || $this->isReservedSubdomain($candidate)) {
return null;
}
$username = User::query()
->whereRaw('LOWER(username) = ?', [$candidate])
->value('username');
if (is_string($username) && $username !== '') {
return UsernamePolicy::normalize($username);
}
if (! Schema::hasTable('username_redirects')) {
return null;
}
$redirect = DB::table('username_redirects')
->whereRaw('LOWER(old_username) = ?', [$candidate])
->value('new_username');
return is_string($redirect) && $redirect !== ''
? UsernamePolicy::normalize($redirect)
: null;
}
private function isReservedSubdomain(string $candidate): bool
{
$reserved = UsernamePolicy::reserved();
foreach ([config('cp.webroot'), config('cpad.webroot')] as $prefix) {
$value = strtolower(trim((string) $prefix, '/'));
if ($value !== '') {
$reserved[] = $value;
}
}
return in_array($candidate, array_values(array_unique($reserved)), true);
}
private function targetUrl(Request $request, string $username): string
{
$canonicalPath = match ($request->getPathInfo()) {
'/gallery', '/gallery/' => '/@' . $username . '/gallery',
default => '/@' . $username,
};
$target = rtrim((string) config('app.url'), '/') . $canonicalPath;
$query = $request->getQueryString();
if (is_string($query) && $query !== '') {
$target .= '?' . $query;
}
return $target;
}
}