From cacf574da416ea15703bfe081772387dda1f44c0 Mon Sep 17 00:00:00 2001 From: Kjell Kind Date: Mon, 26 Oct 2026 22:05:47 +0100 Subject: [PATCH 1/2] fix: find suggested users by their profile handle #990 looked users up by the username column, which #1156 moved to profiles, so a profile context or a dismissal answered 500 or ignored the profile. Co-Authored-By: Claude Opus 5.5 --- app/Http/Requests/ListApiSuggestedUsersRequest.php | 9 ++++++--- routes/api.php | 2 +- .../Controllers/Api/SuggestedUserControllerTest.php | 10 +++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/app/Http/Requests/ListApiSuggestedUsersRequest.php b/app/Http/Requests/ListApiSuggestedUsersRequest.php index 1003d56fc..a53d1861d 100644 --- a/app/Http/Requests/ListApiSuggestedUsersRequest.php +++ b/app/Http/Requests/ListApiSuggestedUsersRequest.php @@ -4,11 +4,14 @@ namespace App\Http\Requests; +use App\Enums\ProfileType; use App\Models\Commit; use App\Models\User; use App\Rules\VisibleCommit; use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Foundation\Http\FormRequest; +use Illuminate\Validation\Rule; +use Illuminate\Validation\Rules\Exists; /** * Who to follow may be asked for the page it shows on, as the web asks for it beside a profile or a commit. The commit @@ -17,7 +20,7 @@ final class ListApiSuggestedUsersRequest extends FormRequest { /** - * @return array> + * @return array> */ public function rules(): array { @@ -26,7 +29,7 @@ public function rules(): array return [ 'round' => ['nullable', 'integer', 'min:0'], - 'username' => ['nullable', 'string', 'exists:users,username'], + 'username' => ['nullable', 'string', Rule::exists('profiles', 'handle')->where('type', ProfileType::User->value)], 'commit_id' => ['bail', 'nullable', 'uuid', 'prohibits:username', new VisibleCommit($user, __('That commit is no longer available.'))], ]; } @@ -37,7 +40,7 @@ public function context(): User|Commit|null assert($user instanceof User); return match (true) { - $this->filled('username') => User::query()->where('username', $this->string('username')->value())->firstOrFail(), + $this->filled('username') => User::query()->whereRelation('profile', 'handle', $this->string('username')->value())->firstOrFail(), $this->filled('commit_id') => Commit::query()->visibleTo($user)->findOrFail($this->string('commit_id')->value()), default => null, }; diff --git a/routes/api.php b/routes/api.php index 7fa00c293..e36e4a655 100644 --- a/routes/api.php +++ b/routes/api.php @@ -185,7 +185,7 @@ // Who to Follow... Route::get('me/suggested-users', [SuggestedUserController::class, 'index'])->name('api-suggested-user.index'); - Route::post('users/{user:username}/dismiss', [SuggestionDismissalController::class, 'store'])->name('api-suggestion-dismissal.store'); + Route::post('users/{user:handle}/dismiss', [SuggestionDismissalController::class, 'store'])->name('api-suggestion-dismissal.store'); // User Mute... Route::get('me/muted', [UserMuteController::class, 'index'])->name('api-user-mute.index'); diff --git a/tests/Feature/Controllers/Api/SuggestedUserControllerTest.php b/tests/Feature/Controllers/Api/SuggestedUserControllerTest.php index 1b0aebcc9..ea4eeb622 100644 --- a/tests/Feature/Controllers/Api/SuggestedUserControllerTest.php +++ b/tests/Feature/Controllers/Api/SuggestedUserControllerTest.php @@ -13,7 +13,7 @@ it('suggests people to follow, with why and whether they follow the user', function (): void { $friend = User::factory()->create(); - $vouched = User::factory()->has(Commit::factory())->create(['username' => 'octocat']); + $vouched = User::factory()->has(Commit::factory())->create(['handle' => 'octocat']); $this->user->following()->attach($friend); $friend->following()->attach($vouched); @@ -108,7 +108,7 @@ $profile->following()->attach($followed); - signedApiRequest($this->keyPair, 'GET', route('api-suggested-user.index', ['username' => $profile->username])) + signedApiRequest($this->keyPair, 'GET', route('api-suggested-user.index', ['username' => $profile->handle])) ->assertOk() ->assertJsonPath('data.*.id', [$followed->id, $regular->id]); }); @@ -144,7 +144,7 @@ $people->last()->followers()->attach($people->take(3)); [$webRoute, $context] = $page === 'profile' - ? [route('user.show', $author), ['username' => $author->username]] + ? [route('user.show', $author), ['username' => $author->handle]] : [route('commit.show', [$author, $root]), ['commit_id' => $root->id]]; $web = null; @@ -188,7 +188,7 @@ $regular = signedApiRequest($this->keyPair, 'GET', route('api-suggested-user.index'))->json('data.*.id'); - signedApiRequest($this->keyPair, 'GET', route('api-suggested-user.index', ['username' => $profile->username])) + signedApiRequest($this->keyPair, 'GET', route('api-suggested-user.index', ['username' => $profile->handle])) ->assertOk() ->assertJsonPath('data.*.id', $regular); })->with([ @@ -247,7 +247,7 @@ 'an unknown username' => fn (): array => [['username' => 'nobody-here'], 'username'], 'an unknown commit' => fn (): array => [['commit_id' => '01a16c57-e371-73fb-a4d7-6ad455c9dd57'], 'commit_id'], 'a commit id that is not one' => fn (): array => [['commit_id' => 'latest'], 'commit_id'], - 'a profile and a commit' => fn (): array => [['username' => User::factory()->create()->username, 'commit_id' => Commit::factory()->create()->id], 'commit_id'], + 'a profile and a commit' => fn (): array => [['username' => User::factory()->create()->handle, 'commit_id' => Commit::factory()->create()->id], 'commit_id'], ]); it('refuses a round that is not a whole number from zero', function (mixed $round): void { From 66e402a670f87eaa193b28466918e3958674d84c Mon Sep 17 00:00:00 2001 From: Kjell Kind Date: Mon, 26 Oct 2026 22:10:30 +0100 Subject: [PATCH 2/2] fix: give the readme tests a handle #1157 dropped the username from users. Co-Authored-By: Claude Opus 5.5 --- tests/Feature/Controllers/UserControllerTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Feature/Controllers/UserControllerTest.php b/tests/Feature/Controllers/UserControllerTest.php index fde0e559f..f8b9be053 100644 --- a/tests/Feature/Controllers/UserControllerTest.php +++ b/tests/Feature/Controllers/UserControllerTest.php @@ -704,7 +704,7 @@ }); it('shows the github profile readme on the readme tab, without looking for commits', function (): void { - $user = User::factory()->create(['username' => 'octocat']); + $user = User::factory()->create(['handle' => 'octocat']); Commit::factory()->for($user)->create(); Http::fake([ @@ -720,7 +720,7 @@ }); it('tells the readme tab when github did not answer', function (): void { - $user = User::factory()->create(['username' => 'octocat']); + $user = User::factory()->create(['handle' => 'octocat']); Http::fake(["api.github.com/user/{$user->github_id}" => Http::response(status: 502)]); @@ -730,7 +730,7 @@ it('does not ask github for the readme on the other tabs', function (string $tab): void { Http::preventStrayRequests(); - $user = User::factory()->create(['username' => 'octocat']); + $user = User::factory()->create(['handle' => 'octocat']); $this->get(route('user.show', ['user' => $user, 'tab' => $tab]))->assertOk()->assertInertia(fn ($page) => $page ->where('readme', null));