diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index 17946ee1f..88154e5e3 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -2,8 +2,10 @@ namespace App\Http\Controllers; +use App\Jobs\UpdateUserIdenticonStatus; use App\Models\User; use Illuminate\Http\Request; +use Illuminate\Support\Facades\RateLimiter; class ProfileController extends Controller { @@ -21,4 +23,28 @@ public function show(Request $request, ?User $user = null) abort(404); } + + public function refresh(Request $request) + { + + $user = $request->user(); + + if (! $user->hasConnectedGitHubAccount()) { + return back()->with('error', 'You need to connect your GitHub account to refresh your avatar.'); + } + + // Rate limiting: 1 request per 1 minute per user + $key = 'avatar-refresh:'.$user->id(); + + if (RateLimiter::tooManyAttempts($key, 1)) { + return back()->with('error', 'Please wait 1 minute(s) before refreshing your avatar again.'); + } + + // Record this attempt for 1 minutes + RateLimiter::hit($key, 60); + + UpdateUserIdenticonStatus::dispatchSync($user); + + return back()->with('success', 'Avatar refresh queued! Your profile image will be updated shortly.'); + } } diff --git a/app/Models/User.php b/app/Models/User.php index 87e841cfc..8fe934860 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -123,7 +123,7 @@ public function hasConnectedGitHubAccount(): bool return ! is_null($this->githubId()); } - public function hasIdenticon(): bool + public function hasGithubIdenticon(): bool { return (bool) $this->github_has_identicon; } diff --git a/resources/views/components/avatar.blade.php b/resources/views/components/avatar.blade.php index db261e951..14daa0005 100644 --- a/resources/views/components/avatar.blade.php +++ b/resources/views/components/avatar.blade.php @@ -1,17 +1,19 @@ @props([ 'user', 'unlinked' => false, + 'showRefresh' => false, ]) githubId() && ! $user->hasIdenticon() +$src = $user->githubId() && ! $user->hasGithubIdenticon() ? sprintf('https://avatars.githubusercontent.com/u/%s', $user->githubId()) : asset('https://laravel.io/images/laravelio-icon-gray.svg'); ?> -@unless ($unlinked) - -@endunless +
+ @unless ($unlinked) + + @endunless merge(['class' => 'bg-gray-50']) }} /> -@unless ($unlinked) - -@endunless + @unless ($unlinked) + + @endunless + + @if ($showRefresh && $user->hasConnectedGitHubAccount()) +
+ @csrf + +
+ @endif +
diff --git a/resources/views/users/profile.blade.php b/resources/views/users/profile.blade.php index 304b07ea1..8e9238c85 100644 --- a/resources/views/users/profile.blade.php +++ b/resources/views/users/profile.blade.php @@ -12,7 +12,12 @@ class="w-full bg-center bg-gray-800 h-60 container mx-auto"
- +
diff --git a/routes/web.php b/routes/web.php index 5c7e652f5..cc7abffd3 100644 --- a/routes/web.php +++ b/routes/web.php @@ -70,6 +70,7 @@ Route::get('user/{username?}', [ProfileController::class, 'show'])->name('profile'); Route::put('users/{username}/block', BlockUserController::class)->name('users.block'); Route::put('users/{username}/unblock', UnblockUserController::class)->name('users.unblock'); +Route::post('/avatar/refresh', [ProfileController::class, 'refresh'])->name('avatar.refresh'); // Notifications Route::view('notifications', 'users.notifications')->name('notifications')->middleware(Authenticate::class);