From cb8d2740d70ba616029c6e4e1302715b4016686f Mon Sep 17 00:00:00 2001 From: Bjarn Bronsveld Date: Fri, 2 Oct 2026 18:28:39 +0200 Subject: [PATCH] Fix private comment exposure on profiles --- app/Http/Controllers/PublicUserController.php | 8 +++- .../Controllers/PublicUserControllerTest.php | 43 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/PublicUserController.php b/app/Http/Controllers/PublicUserController.php index 1f71b335..3dac6ebe 100644 --- a/app/Http/Controllers/PublicUserController.php +++ b/app/Http/Controllers/PublicUserController.php @@ -20,6 +20,7 @@ public function __invoke($userName) $data = [ 'items_created' => $user->items()->visibleForCurrentUser()->count(), 'comments_created' => $user->comments() + ->public() ->whereHas('item', fn ($q) => $q->visibleForCurrentUser()) ->count(), 'votes_created' => $user->votes() @@ -27,7 +28,8 @@ public function __invoke($userName) if ($type === Item::class) { $query->visibleForCurrentUser(); } elseif ($type === Comment::class) { - $query->whereHas('item', fn ($q) => $q->visibleForCurrentUser()); + $query->public() + ->whereHas('item', fn ($q) => $q->visibleForCurrentUser()); } }) ->count(), @@ -57,6 +59,7 @@ private function getRecentActivities(User $user): Collection }); $comments = $user->comments() + ->public() ->whereHas('item', fn ($query) => $query->visibleForCurrentUser()) ->with(['item' => fn ($q) => $q->with('project')]) ->latest() @@ -79,7 +82,8 @@ private function getRecentActivities(User $user): Collection if ($type === Item::class) { $query->visibleForCurrentUser(); } elseif ($type === Comment::class) { - $query->whereHas('item', fn ($q) => $q->visibleForCurrentUser()); + $query->public() + ->whereHas('item', fn ($q) => $q->visibleForCurrentUser()); } }) ->with(['model' => function ($query) { diff --git a/tests/Feature/Controllers/PublicUserControllerTest.php b/tests/Feature/Controllers/PublicUserControllerTest.php index e4363c7b..7b151fa1 100644 --- a/tests/Feature/Controllers/PublicUserControllerTest.php +++ b/tests/Feature/Controllers/PublicUserControllerTest.php @@ -74,6 +74,23 @@ ->assertDontSee('Private'); }); +test('hides private comments on public items', function () { + $viewer = User::factory()->create(); + $author = User::factory()->create(); + $item = Item::factory()->create(['private' => false]); + + Comment::factory()->create([ + 'user_id' => $author->id, + 'item_id' => $item->id, + 'content' => 'Private profile note', + 'private' => true, + ]); + + actingAs($viewer) + ->get(route('public-user', $author->username)) + ->assertDontSee('Private profile note'); +}); + test('hides comments on items in private projects', function () { $viewer = User::factory()->create(); $author = User::factory()->create(); @@ -131,6 +148,27 @@ ->assertDontSee('Hidden Comment'); }); +test('hides votes on private comments', function () { + $viewer = User::factory()->create(); + $voter = User::factory()->create(); + $item = Item::factory()->create(['title' => 'Public Item', 'private' => false]); + $comment = Comment::factory()->create([ + 'item_id' => $item->id, + 'content' => 'Private voted note', + 'private' => true, + ]); + + Vote::factory()->create([ + 'user_id' => $voter->id, + 'model_type' => Comment::class, + 'model_id' => $comment->id, + ]); + + actingAs($viewer) + ->get(route('public-user', $voter->username)) + ->assertDontSee('Private voted note'); +}); + test('counts only visible items', function () { $viewer = User::factory()->create(); $author = User::factory()->create(); @@ -151,6 +189,11 @@ $privateItem = Item::factory()->create(['private' => true]); Comment::factory()->count(2)->create(['user_id' => $author->id, 'item_id' => $publicItem->id]); + Comment::factory()->create([ + 'user_id' => $author->id, + 'item_id' => $publicItem->id, + 'private' => true, + ]); Comment::factory()->create(['user_id' => $author->id, 'item_id' => $privateItem->id]); $response = actingAs($viewer)->get(route('public-user', $author->username));