From 6201d45f59b0492566bf40a9651328c8d32a479b Mon Sep 17 00:00:00 2001 From: Gabriel do Carmo Vieira <48625433+gvieira18@users.noreply.github.com> Date: Thu, 23 Jul 2026 09:18:24 -0300 Subject: [PATCH 1/2] fix(portal): resolve hero avatars by user id Use the stable GitHub numeric account id to build avatar URLs instead of parsing the metadata username, which could be stale. --- .../portal/src/Livewire/HeroSection.php | 15 ++--- .../portal/tests/Feature/HeroAvatarsTest.php | 66 +++++++++++++++++++ 2 files changed, 70 insertions(+), 11 deletions(-) create mode 100644 app-modules/portal/tests/Feature/HeroAvatarsTest.php diff --git a/app-modules/portal/src/Livewire/HeroSection.php b/app-modules/portal/src/Livewire/HeroSection.php index 02042dc45..72898075f 100644 --- a/app-modules/portal/src/Livewire/HeroSection.php +++ b/app-modules/portal/src/Livewire/HeroSection.php @@ -78,22 +78,15 @@ private function fetchAvatars(): array return []; } - /** @param array $metadata */ - $githubHandle = static function (array $metadata): ?string { - $handle = $metadata['username'] ?? $metadata['name'] ?? null; - - return is_string($handle) ? $handle : null; - }; - return ExternalIdentity::query() ->where('provider', IdentityProvider::GitHub) ->whereIn('model_id', $activeUserIds) + ->whereNotNull('external_account_id') ->inRandomOrder() ->limit(10) - ->pluck('metadata') - ->map(fn (array $metadata) => $githubHandle($metadata)) - ->filter() - ->map(fn (string $handle) => sprintf('https://github.com/%s.png', $handle)) + ->pluck('external_account_id') + ->filter(fn (?string $id): bool => is_string($id) && ctype_digit($id)) + ->map(fn (string $id) => sprintf('https://avatars.githubusercontent.com/u/%s?v=4', $id)) ->values() ->all(); } diff --git a/app-modules/portal/tests/Feature/HeroAvatarsTest.php b/app-modules/portal/tests/Feature/HeroAvatarsTest.php new file mode 100644 index 000000000..223e0bb9b --- /dev/null +++ b/app-modules/portal/tests/Feature/HeroAvatarsTest.php @@ -0,0 +1,66 @@ + 20 mensagens nos últimos + * 30 dias) e vincula uma identidade GitHub a ele. + */ +function activeUserWithGithub(string $externalAccountId): User +{ + $user = User::factory()->create(); + + $discordIdentity = ExternalIdentity::factory()->create([ + 'model_type' => $user->getMorphClass(), + 'model_id' => $user->id, + 'provider' => IdentityProvider::Discord, + ]); + + Message::factory()->count(21)->create([ + 'external_identity_id' => $discordIdentity->id, + 'sent_at' => now()->subDay(), + ]); + + ExternalIdentity::factory()->create([ + 'model_type' => $user->getMorphClass(), + 'model_id' => $user->id, + 'provider' => IdentityProvider::GitHub, + 'external_account_id' => $externalAccountId, + ]); + + return $user; +} + +it('monta avatares a partir do CDN do GitHub usando o id numérico da conta', function (): void { + activeUserWithGithub('583231'); + + $avatars = livewire(HeroSection::class)->instance()->avatars(); + + expect($avatars)->toContain('https://avatars.githubusercontent.com/u/583231?v=4'); +}); + +it('nunca aponta os avatares para github.com (evita o Set-Cookie cross-site)', function (): void { + activeUserWithGithub('583231'); + + $avatars = livewire(HeroSection::class)->instance()->avatars(); + + expect($avatars)->not->toBeEmpty() + ->and(collect($avatars)->every(fn (string $url): bool => !str_contains($url, 'github.com/'))) + ->toBeTrue(); +}); + +it('ignora identidades GitHub cujo external_account_id não é numérico', function (): void { + activeUserWithGithub('not-a-numeric-id'); + + $avatars = livewire(HeroSection::class)->instance()->avatars(); + + expect($avatars)->toBeEmpty(); +}); From f12e06c98e9a5d1f8d53f9b39f5f08282d8d3cd2 Mon Sep 17 00:00:00 2001 From: Gabriel do Carmo Vieira <48625433+gvieira18@users.noreply.github.com> Date: Thu, 23 Jul 2026 09:25:26 -0300 Subject: [PATCH 2/2] fix(portal): filter numeric github ids in sql query --- app-modules/portal/src/Livewire/HeroSection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app-modules/portal/src/Livewire/HeroSection.php b/app-modules/portal/src/Livewire/HeroSection.php index 72898075f..e44252ce2 100644 --- a/app-modules/portal/src/Livewire/HeroSection.php +++ b/app-modules/portal/src/Livewire/HeroSection.php @@ -82,10 +82,10 @@ private function fetchAvatars(): array ->where('provider', IdentityProvider::GitHub) ->whereIn('model_id', $activeUserIds) ->whereNotNull('external_account_id') + ->whereRaw("external_account_id ~ '^[0-9]+$'") ->inRandomOrder() ->limit(10) ->pluck('external_account_id') - ->filter(fn (?string $id): bool => is_string($id) && ctype_digit($id)) ->map(fn (string $id) => sprintf('https://avatars.githubusercontent.com/u/%s?v=4', $id)) ->values() ->all();