Auth: convert auth views and verification email to Nova layout

This commit is contained in:
2026-02-21 07:37:08 +01:00
parent 93b009d42a
commit 795c7a835f
117 changed files with 5385 additions and 1291 deletions

View File

@@ -4,9 +4,15 @@ namespace App\Http\Controllers\User;
use App\Http\Controllers\Controller;
use App\Http\Requests\ProfileUpdateRequest;
use App\Models\Artwork;
use App\Models\User;
use App\Services\ArtworkService;
use App\Services\UsernameApprovalService;
use App\Support\UsernamePolicy;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redirect;
use Illuminate\View\View;
use Illuminate\Support\Facades\Hash;
@@ -14,6 +20,49 @@ use Illuminate\Validation\Rules\Password as PasswordRule;
class ProfileController extends Controller
{
public function __construct(
private readonly ArtworkService $artworkService,
private readonly UsernameApprovalService $usernameApprovalService,
)
{
}
public function showByUsername(Request $request, string $username)
{
$normalized = UsernamePolicy::normalize($username);
$user = User::query()->whereRaw('LOWER(username) = ?', [$normalized])->first();
if (! $user) {
$redirect = DB::table('username_redirects')
->whereRaw('LOWER(old_username) = ?', [$normalized])
->value('new_username');
if ($redirect) {
return redirect()->route('profile.show', ['username' => strtolower((string) $redirect)], 301);
}
abort(404);
}
if ($username !== strtolower((string) $user->username)) {
return redirect()->route('profile.show', ['username' => strtolower((string) $user->username)], 301);
}
return $this->renderUserProfile($request, $user);
}
public function legacyById(Request $request, int $id, ?string $username = null)
{
$user = User::query()->findOrFail($id);
return redirect()->route('profile.show', ['username' => strtolower((string) $user->username)], 301);
}
public function legacyByUsername(Request $request, string $username)
{
return redirect()->route('profile.show', ['username' => UsernamePolicy::normalize($username)], 301);
}
public function edit(Request $request): View
{
return view('profile.edit', [
@@ -33,6 +82,56 @@ class ProfileController extends Controller
$user->name = $validated['name'];
}
if (array_key_exists('username', $validated)) {
$incomingUsername = UsernamePolicy::normalize((string) $validated['username']);
$currentUsername = UsernamePolicy::normalize((string) ($user->username ?? ''));
if ($incomingUsername !== '' && $incomingUsername !== $currentUsername) {
$similar = UsernamePolicy::similarReserved($incomingUsername);
if ($similar !== null && ! UsernamePolicy::hasApprovedOverride($incomingUsername, (int) $user->id)) {
$this->usernameApprovalService->submit($user, $incomingUsername, 'profile_update', [
'current_username' => $currentUsername,
]);
return Redirect::back()->withErrors([
'username' => 'This username is too similar to a reserved name and requires manual approval.',
]);
}
$cooldownDays = (int) config('usernames.rename_cooldown_days', 90);
$isAdmin = method_exists($user, 'isAdmin') ? $user->isAdmin() : false;
if (! $isAdmin && $user->username_changed_at !== null && $user->username_changed_at->gt(now()->subDays($cooldownDays))) {
return Redirect::back()->withErrors([
'username' => "Username can only be changed once every {$cooldownDays} days.",
]);
}
$user->username = $incomingUsername;
$user->username_changed_at = now();
DB::table('username_history')->insert([
'user_id' => (int) $user->id,
'old_username' => $currentUsername,
'changed_at' => now(),
'created_at' => now(),
'updated_at' => now(),
]);
if ($currentUsername !== '') {
DB::table('username_redirects')->updateOrInsert(
['old_username' => $currentUsername],
[
'new_username' => $incomingUsername,
'user_id' => (int) $user->id,
'updated_at' => now(),
'created_at' => now(),
]
);
}
}
}
if (!empty($validated['email']) && empty($user->email)) {
$user->email = $validated['email'];
$user->email_verified_at = null;
@@ -154,4 +253,41 @@ class ProfileController extends Controller
return Redirect::to('/user')->with('status', 'password-updated');
}
private function renderUserProfile(Request $request, User $user)
{
$isOwner = Auth::check() && Auth::id() === $user->id;
$perPage = 24;
$artworks = $this->artworkService->getArtworksByUser($user->id, $isOwner, $perPage)
->through(function (Artwork $art) {
$present = \App\Services\ThumbnailPresenter::present($art, 'md');
return (object) [
'id' => $art->id,
'name' => $art->title,
'picture' => $art->file_name,
'datum' => $art->published_at,
'thumb' => $present['url'],
'thumb_srcset' => $present['srcset'] ?? $present['url'],
'uname' => $art->user->name ?? 'Skinbase',
];
});
$legacyUser = (object) [
'user_id' => $user->id,
'uname' => $user->username ?? $user->name,
'name' => $user->name,
'real_name' => $user->name,
'icon' => DB::table('user_profiles')->where('user_id', $user->id)->value('avatar_hash'),
'about_me' => $user->bio ?? null,
];
return response()->view('legacy.profile', [
'user' => $legacyUser,
'artworks' => $artworks,
'page_title' => 'Profile: ' . ($legacyUser->uname ?? ''),
'page_canonical' => url('/@' . strtolower((string) ($user->username ?? ''))),
]);
}
}

View File

@@ -20,7 +20,7 @@ class UserController extends Controller
$profile = null;
}
return view('user.user', [
return view('legacy.user', [
'profile' => $profile,
]);
}