From b74e5ce5cd707817b1ccd201ca4d548a16f02af6 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 11 Sep 2025 22:22:46 +1200 Subject: [PATCH] Block bulk ops through txn create multi ops --- .../Databases/Transactions/Operations/Create.php | 15 ++++++++++++++- .../Utopia/Database/Validator/Operation.php | 10 ++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php index 58505591ff..a33af05e3d 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Operations/Create.php @@ -2,6 +2,7 @@ namespace Appwrite\Platform\Modules\Databases\Http\Databases\Transactions\Operations; +use Appwrite\Auth\Auth; use Appwrite\Extend\Exception; use Appwrite\Platform\Modules\Databases\Http\Databases\Transactions\Action; use Appwrite\SDK\AuthType; @@ -13,6 +14,7 @@ use Appwrite\Utopia\Response as UtopiaResponse; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Swoole\Response as SwooleResponse; use Utopia\Validator\ArrayList; @@ -43,7 +45,7 @@ class Create extends Action group: 'transactions', name: 'createOperations', description: '/docs/references/databases/create-operations.md', - auth: [AuthType::KEY], + auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT], responses: [ new SDKResponse( code: SwooleResponse::STATUS_CODE_CREATED, @@ -77,8 +79,19 @@ class Create extends Action ); } + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + $databases = $collections = $staged = []; foreach ($operations as $operation) { + if (!$isAPIKey && !$isPrivilegedUser && \in_array($operation['action'], [ + 'bulkCreate', + 'bulkUpdate', + 'bulkDelete' + ])) { + throw new Exception(Exception::USER_UNAUTHORIZED); + } + $database = $databases[$operation['databaseId']] ??= $dbForProject->getDocument('databases', $operation['databaseId']); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); diff --git a/src/Appwrite/Utopia/Database/Validator/Operation.php b/src/Appwrite/Utopia/Database/Validator/Operation.php index ec2d4f0d49..f3fe2375b0 100644 --- a/src/Appwrite/Utopia/Database/Validator/Operation.php +++ b/src/Appwrite/Utopia/Database/Validator/Operation.php @@ -64,6 +64,16 @@ class Operation extends Validator return $this->description; } + public function getCollectionIdName(): string + { + return $this->collectionIdName; + } + + public function getDocumentIdName(): string + { + return $this->documentIdName; + } + public function isArray(): bool { return true;