From 99e9ff1f44264c0290fb44cf63f0c86a86234a33 Mon Sep 17 00:00:00 2001 From: addshore Date: Wed, 4 Nov 2026 23:41:36 +0000 Subject: [PATCH] Lock user on wiki creation to avoid race request possibly exceeding quota --- app/Http/Controllers/WikiController.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/WikiController.php b/app/Http/Controllers/WikiController.php index 3e881792..b0475e3d 100644 --- a/app/Http/Controllers/WikiController.php +++ b/app/Http/Controllers/WikiController.php @@ -13,6 +13,7 @@ use App\Jobs\ProvisionWikiDbJob; use App\KnowledgeEquityResponse; use App\QueryserviceNamespace; +use App\User; use App\Wiki; use App\WikiDb; use App\WikiDomain; @@ -87,6 +88,10 @@ public function create(Request $request): Response { // TODO create with some sort of owner etc? DB::transaction(function () use ($user, $request, &$wiki, &$dbAssignment, $submittedDomain, $rawProfile, $rawKnowledgeEquityResponse): void { + // Lock the user before any reads establish a repeatable-read snapshot. + // Creation always locks in this order: user, wiki DB, then QS namespace. + $user = User::whereKey($user->getKey())->lockForUpdate()->firstOrFail(); + $dbVersion = Config::get('wbstack.wiki_db_use_version'); $wikiDbCondition = ['wiki_id' => null, 'version' => $dbVersion]; @@ -101,7 +106,7 @@ public function create(Request $request): Response { $numWikis = $user->managesWikis()->count() + 1; $maxWikis = config('wbstack.wiki_max_per_user'); - if (config('wbstack.wiki_max_per_user') !== false && $numWikis > config('wbstack.wiki_max_per_user')) { + if ($maxWikis !== false && $numWikis > $maxWikis) { abort(403, "Too many wikis. Your new total of {$numWikis} would exceed the limit of {$maxWikis} per user."); }