diff --git a/routes/api.php b/routes/api.php index 59c88722b..67cc0a186 100644 --- a/routes/api.php +++ b/routes/api.php @@ -384,7 +384,7 @@ // Remotes: finding people to push to, and starting an org, as the web's New remote and New org do... Route::middleware('throttle:conversations')->group(function (): void { Route::get('remotes/candidates', [RemoteCandidateController::class, 'index'])->name('api-remote-candidate.index'); - Route::post('remotes/orgs', [OrgController::class, 'store'])->middleware('throttle:messages')->name('api-org.store'); + Route::post('remotes/orgs', [OrgController::class, 'store'])->middleware([PreventPostingInTimeout::class, 'throttle:messages'])->name('api-org.store'); }); // Remotes: renaming an org and managing its members, as the web's org settings do... diff --git a/tests/Feature/Controllers/Api/OrgControllerTest.php b/tests/Feature/Controllers/Api/OrgControllerTest.php index 481a25101..b9d0b5b3f 100644 --- a/tests/Feature/Controllers/Api/OrgControllerTest.php +++ b/tests/Feature/Controllers/Api/OrgControllerTest.php @@ -35,6 +35,18 @@ ->and(Message::query()->sole()->event)->toBe(OrgEvent::Created); }); +it('refuses to start an org for a user in timeout, as the web does', function (): void { + [$nuno] = followersOf($this->user, 1); + UserTimeout::factory()->for($this->user)->create(); + + signedApiRequest($this->keyPair, 'POST', route('api-org.store'), ['name' => 'buy my course', 'members' => [$nuno->handle]]) + ->assertForbidden() + ->assertJsonPath('code', 'timed_out'); + + expect(Conversation::query()->exists())->toBeFalse() + ->and(Message::query()->exists())->toBeFalse(); +}); + it('leaves an org without a name when none is given', function (?string $name): void { [$nuno] = followersOf($this->user, 1);