diff --git a/app-modules/portal/src/Livewire/HeroSection.php b/app-modules/portal/src/Livewire/HeroSection.php index 02042dc4..e44252ce 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') + ->whereRaw("external_account_id ~ '^[0-9]+$'") ->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') + ->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 00000000..223e0bb9 --- /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(); +});