diff --git a/app/controllers/general.php b/app/controllers/general.php index 61ff689a5c..72c5ce4c15 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1028,107 +1028,107 @@ Http::init() * Automatic certificate generation */ Http::init() - ->groups(['api', 'web']) - ->inject('request') - ->inject('console') - ->inject('dbForPlatform') - ->inject('queueForCertificates') - ->inject('platform') + ->groups(['api', 'web']) + ->inject('request') + ->inject('console') + ->inject('dbForPlatform') + ->inject('queueForCertificates') + ->inject('platform') ->inject('authorization') ->inject('certifiedDomains') - ->action(function (Request $request, Document $console, Database $dbForPlatform, Certificate $queueForCertificates, array $platform, Authorization $authorization, Table $certifiedDomains) { - $hostname = $request->getHostname(); - $platformHostnames = $platform['hostnames'] ?? []; + ->action(function (Request $request, Document $console, Database $dbForPlatform, Certificate $queueForCertificates, array $platform, Authorization $authorization, Table $certifiedDomains) { + $hostname = $request->getHostname(); + $platformHostnames = $platform['hostnames'] ?? []; - // 1. Cache hit - if ($certifiedDomains->exists(md5($hostname))) { - return; - } + // 1. Cache hit + if ($certifiedDomains->exists(md5($hostname))) { + return; + } - // 2. Domain validation - $domain = new Domain(!empty($hostname) ? $hostname : ''); - if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()) { - $certifiedDomains->set(md5($domain->get()), ['value' => 0]); - return; - } + // 2. Domain validation + $domain = new Domain(!empty($hostname) ? $hostname : ''); + if (empty($domain->get()) || !$domain->isKnown() || $domain->isTest()) { + $certifiedDomains->set(md5($domain->get()), ['value' => 0]); + return; + } - if (str_starts_with($request->getURI(), '/.well-known/acme-challenge')) { - return; - } + if (str_starts_with($request->getURI(), '/.well-known/acme-challenge')) { + return; + } - // 3. Check if domain is a main domain - if (!in_array($domain->get(), $platformHostnames)) { - return; - } + // 3. Check if domain is a main domain + if (!in_array($domain->get(), $platformHostnames)) { + return; + } - // 4. Check/create rule (requires DB access) - $authorization->skip(function () use ($dbForPlatform, $domain, $console, $queueForCertificates, $certifiedDomains) { - try { - // TODO: (@Meldiron) Remove after 1.7.x migration - $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; - $document = $isMd5 - ? $dbForPlatform->getDocument('rules', md5($domain->get())) - : $dbForPlatform->findOne('rules', [ - Query::equal('domain', [$domain->get()]), - ]); + // 4. Check/create rule (requires DB access) + $authorization->skip(function () use ($dbForPlatform, $domain, $console, $queueForCertificates, $certifiedDomains) { + try { + // TODO: (@Meldiron) Remove after 1.7.x migration + $isMd5 = System::getEnv('_APP_RULES_FORMAT') === 'md5'; + $document = $isMd5 + ? $dbForPlatform->getDocument('rules', md5($domain->get())) + : $dbForPlatform->findOne('rules', [ + Query::equal('domain', [$domain->get()]), + ]); - if (!$document->isEmpty()) { - return; - } + if (!$document->isEmpty()) { + return; + } - // 5. Create new rule - $owner = ''; + // 5. Create new rule + $owner = ''; - // Mark owner as Appwrite if its appwrite-owned domain - $appwriteDomains = []; - $appwriteDomainEnvs = [ - System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''), - System::getEnv('_APP_DOMAIN_FUNCTIONS', ''), - System::getEnv('_APP_DOMAIN_SITES', ''), - ]; - foreach ($appwriteDomainEnvs as $appwriteDomainEnv) { - foreach (\explode(',', $appwriteDomainEnv) as $appwriteDomain) { - if (empty($appwriteDomain)) { - continue; - } - $appwriteDomains[] = $appwriteDomain; - } - } + // Mark owner as Appwrite if its appwrite-owned domain + $appwriteDomains = []; + $appwriteDomainEnvs = [ + System::getEnv('_APP_DOMAIN_FUNCTIONS_FALLBACK', ''), + System::getEnv('_APP_DOMAIN_FUNCTIONS', ''), + System::getEnv('_APP_DOMAIN_SITES', ''), + ]; + foreach ($appwriteDomainEnvs as $appwriteDomainEnv) { + foreach (\explode(',', $appwriteDomainEnv) as $appwriteDomain) { + if (empty($appwriteDomain)) { + continue; + } + $appwriteDomains[] = $appwriteDomain; + } + } - foreach ($appwriteDomains as $appwriteDomain) { - if (\str_ends_with($domain->get(), $appwriteDomain)) { - $owner = 'Appwrite'; - break; - } - } + foreach ($appwriteDomains as $appwriteDomain) { + if (\str_ends_with($domain->get(), $appwriteDomain)) { + $owner = 'Appwrite'; + break; + } + } - $ruleId = $isMd5 ? md5($domain->get()) : ID::unique(); - $document = new Document([ - '$id' => $ruleId, - 'domain' => $domain->get(), - 'type' => 'api', - 'status' => 'verifying', - 'projectId' => $console->getId(), - 'projectInternalId' => $console->getSequence(), - 'search' => implode(' ', [$ruleId, $domain->get()]), - 'owner' => $owner, - 'region' => $console->getAttribute('region') - ]); + $ruleId = $isMd5 ? md5($domain->get()) : ID::unique(); + $document = new Document([ + '$id' => $ruleId, + 'domain' => $domain->get(), + 'type' => 'api', + 'status' => 'verifying', + 'projectId' => $console->getId(), + 'projectInternalId' => $console->getSequence(), + 'search' => implode(' ', [$ruleId, $domain->get()]), + 'owner' => $owner, + 'region' => $console->getAttribute('region') + ]); - $dbForPlatform->createDocument('rules', $document); + $dbForPlatform->createDocument('rules', $document); - Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...'); - $queueForCertificates - ->setDomain($document) - ->setSkipRenewCheck(true) - ->trigger(); - } catch (Duplicate $e) { - Console::info('Certificate already exists'); - } finally { - $certifiedDomains->set(md5($domain->get()), ['value' => 1]); - } - }); - }); + Console::info('Issuing a TLS certificate for the main domain (' . $domain->get() . ') in a few seconds...'); + $queueForCertificates + ->setDomain($document) + ->setSkipRenewCheck(true) + ->trigger(); + } catch (Duplicate $e) { + Console::info('Certificate already exists'); + } finally { + $certifiedDomains->set(md5($domain->get()), ['value' => 1]); + } + }); + }); Http::options() ->inject('utopia') diff --git a/composer.json b/composer.json index f2263b4b4c..d3474361e2 100644 --- a/composer.json +++ b/composer.json @@ -112,7 +112,6 @@ }, "config": { "platform": { - "php": "8.3" }, "allow-plugins": { "php-http/discovery": true, diff --git a/composer.lock b/composer.lock index 29643c7b08..123b2c88a1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "74c4ce8bc6eb2ee021ff2f867939cf16", + "content-hash": "9a409fa43f22650e15a20e0eaaaa4c24", "packages": [ { "name": "adhocore/jwt", @@ -8519,8 +8519,5 @@ "platform-dev": { "ext-fileinfo": "*" }, - "platform-overrides": { - "php": "8.3" - }, "plugin-api-version": "2.9.0" } diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index 5d80044527..ae75e3924f 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -519,6 +519,7 @@ class Event * @param string $pattern * @param array $params * @param ?Document $database + * @param ?Document $database * @return array * @throws \InvalidArgumentException */ diff --git a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php index 9f0839a14b..0c8c6a8520 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/Databases/Transactions/Update.php @@ -180,35 +180,21 @@ class Update extends Action } $dbForDatabases = $getDatabasesDB($databaseDoc); - $collections = []; try { - $transaction = $authorization->skip(fn () => $dbForProject->updateDocument( - 'transactions', - $transactionId, - new Document(['status' => 'committing']) - )); + $dbForDatabases->withTransaction(function () use ($dbForDatabases, $dbForProject, $transactionState, $queueForDeletes, $transactionId, &$transaction, &$operations, &$totalOperations, &$databaseOperations, &$currentDocumentId, $authorization) { + $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ + 'status' => 'committing', + ]))); - $operations = $authorization->skip(fn () => $dbForProject->find('transactionLogs', [ - Query::equal('transactionInternalId', [$transaction->getSequence()]), - Query::orderAsc(), - Query::limit(PHP_INT_MAX), - ])); + $operations = $authorization->skip(fn () => $dbForProject->find('transactionLogs', [ + Query::equal('transactionInternalId', [$transaction->getSequence()]), + Query::orderAsc(), + Query::limit(PHP_INT_MAX), + ])); - foreach ($operations as $operation) { - $databaseInternalId = $operation['databaseInternalId']; - $collectionInternalId = $operation['collectionInternalId']; - $collectionId = "database_{$databaseInternalId}_collection_{$collectionInternalId}"; - - if (!isset($collections[$collectionId])) { - $collections[$collectionId] = $authorization->skip( - fn () => $dbForProject->getCollection($collectionId) - ); - } - } - - $dbForDatabases->withTransaction(function () use ($dbForDatabases, $transactionState, $operations, $collections, &$totalOperations, &$databaseOperations, &$currentDocumentId) { $state = []; + $collections = []; foreach ($operations as $operation) { $databaseInternalId = $operation['databaseInternalId']; @@ -224,6 +210,11 @@ class Update extends Action $data = $data->getArrayCopy(); } + if (!isset($collections[$collectionId])) { + $collections[$collectionId] = $authorization->skip( + fn () => $dbForProject->getCollection($collectionId) + ); + } $collection = $collections[$collectionId]; if (\is_array($data) && !empty($data)) { @@ -284,17 +275,17 @@ class Update extends Action break; } } + + $transaction = $authorization->skip(fn () => $dbForProject->updateDocument( + 'transactions', + $transactionId, + new Document(['status' => 'committed']) + )); + + $queueForDeletes + ->setType(DELETE_TYPE_DOCUMENT) + ->setDocument($transaction); }); - - $transaction = $authorization->skip(fn () => $dbForProject->updateDocument( - 'transactions', - $transactionId, - new Document(['status' => 'committed']) - )); - - $queueForDeletes - ->setType(DELETE_TYPE_DOCUMENT) - ->setDocument($transaction); } catch (NotFoundException $e) { $authorization->skip(fn () => $dbForProject->updateDocument('transactions', $transactionId, new Document([ 'status' => 'failed', diff --git a/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Collections/Create.php b/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Collections/Create.php index baa31c4ef7..a7e2d68eac 100644 --- a/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Collections/Create.php +++ b/src/Appwrite/Platform/Modules/Databases/Http/VectorsDB/Collections/Create.php @@ -20,7 +20,6 @@ use Utopia\Database\Exception\Limit as LimitException; use Utopia\Database\Exception\NotFound as NotFoundException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; -use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\Permissions; use Utopia\Database\Validator\UID; @@ -117,30 +116,6 @@ class Create extends CollectionAction } /** @var Database $dbForDatabases */ $dbForDatabases = $getDatabasesDB($database); - $cleanupCollection = function () use ($authorization, $dbForProject, $database, $collection): void { - try { - $authorization->skip(fn () => $dbForProject->deleteDocument( - 'database_' . $database->getSequence(), - $collection->getId() - )); - } catch (\Throwable) { - } - - $queries = [ - Query::equal('databaseInternalId', [$database->getSequence()]), - Query::equal('collectionInternalId', [$collection->getSequence()]), - ]; - - try { - $authorization->skip(fn () => $dbForProject->deleteDocuments('attributes', $queries)); - } catch (\Throwable) { - } - - try { - $authorization->skip(fn () => $dbForProject->deleteDocuments('indexes', $queries)); - } catch (\Throwable) { - } - }; $attributes = []; $indexes = []; @@ -159,10 +134,6 @@ class Create extends CollectionAction try { $dbForDatabases->create(); } catch (DuplicateException) { - } catch (\Throwable $e) { - if (!$dbForDatabases->exists(null, Database::METADATA)) { - throw $e; - } } } $dbForDatabases->createCollection( @@ -220,17 +191,11 @@ class Create extends CollectionAction $dbForProject->createDocuments('indexes', $indexDocs); } } catch (DuplicateException) { - $cleanupCollection(); throw new Exception($this->getDuplicateException()); } catch (IndexException) { - $cleanupCollection(); throw new Exception($this->getInvalidIndexException()); } catch (LimitException) { - $cleanupCollection(); throw new Exception($this->getLimitException()); - } catch (\Throwable $e) { - $cleanupCollection(); - throw $e; } $queueForEvents diff --git a/src/Utopia/Bus/Bus.php b/src/Utopia/Bus/Bus.php index 0ff95205be..bef39f0481 100644 --- a/src/Utopia/Bus/Bus.php +++ b/src/Utopia/Bus/Bus.php @@ -2,7 +2,6 @@ namespace Utopia\Bus; -use Utopia\Console; use Utopia\Span\Span; class Bus @@ -44,7 +43,6 @@ class Bus ($listener->getCallback())($event, ...$deps); } catch (\Throwable $e) { Span::error($e); - Console::error('[Bus] Listener ' . $listener::getName() . ' failed: ' . $e->getMessage()); } finally { Span::current()?->finish(); }