diff --git a/src/Appwrite/Platform/Modules/Proxy/Action.php b/src/Appwrite/Platform/Modules/Proxy/Action.php index 8baf54c790..5c239708c9 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Action.php +++ b/src/Appwrite/Platform/Modules/Proxy/Action.php @@ -5,7 +5,11 @@ namespace Appwrite\Platform\Modules\Proxy; use Appwrite\Extend\Exception; use Appwrite\Network\Validator\DNS as ValidatorDNS; use Appwrite\Platform\Action as PlatformAction; +use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Exception\Duplicate; +use Utopia\Database\Query; +use Utopia\Database\Validator\Authorization; use Utopia\DNS\Message\Record; use Utopia\Domains\Domain; use Utopia\Logger\Log; @@ -20,6 +24,54 @@ class Action extends PlatformAction { } + protected function createRule(Document $rule, Database $dbForPlatform, Authorization $authorization): Document + { + try { + return $authorization->skip(fn () => $dbForPlatform->createDocument('rules', $rule)); + } catch (Duplicate) { + if (!$this->deleteOrphanedRule($rule, $dbForPlatform, $authorization)) { + throw new Exception(Exception::RULE_ALREADY_EXISTS); + } + } + + try { + return $authorization->skip(fn () => $dbForPlatform->createDocument('rules', $rule)); + } catch (Duplicate) { + throw new Exception(Exception::RULE_ALREADY_EXISTS); + } + } + + private function deleteOrphanedRule(Document $rule, Database $dbForPlatform, Authorization $authorization): bool + { + $existingRule = $authorization->skip(function () use ($rule, $dbForPlatform) { + $existingRule = $dbForPlatform->findOne('rules', [ + Query::equal('domain', [$rule->getAttribute('domain', '')]), + ]); + + if (!$existingRule->isEmpty()) { + return $existingRule; + } + + return $dbForPlatform->getDocument('rules', $rule->getId()); + }); + + if ($existingRule->isEmpty()) { + return false; + } + + $project = $authorization->skip( + fn () => $dbForPlatform->getDocument('projects', $existingRule->getAttribute('projectId', '')) + ); + + if (!$project->isEmpty()) { + return false; + } + + $authorization->skip(fn () => $dbForPlatform->deleteDocument('rules', $existingRule->getId())); + + return true; + } + /** * Ensures domain is not in the deny list and is a valid domain * diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php index 6f2e40d13f..9431d24cde 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; use Utopia\Logger\Log; @@ -120,11 +119,7 @@ class Create extends Action } } - try { - $rule = $authorization->skip(fn () => $dbForPlatform->createDocument('rules', $rule)); - } catch (Duplicate $e) { - throw new Exception(Exception::RULE_ALREADY_EXISTS); - } + $rule = $this->createRule($rule, $dbForPlatform, $authorization); if ($rule->getAttribute('status', '') === RULE_STATUS_CERTIFICATE_GENERATING) { $publisherForCertificates->enqueue(new \Appwrite\Event\Message\Certificate( diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php index c68574fefe..7cc8b5e59e 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; @@ -142,11 +141,7 @@ class Create extends Action } } - try { - $rule = $authorization->skip(fn () => $dbForPlatform->createDocument('rules', $rule)); - } catch (Duplicate $e) { - throw new Exception(Exception::RULE_ALREADY_EXISTS); - } + $rule = $this->createRule($rule, $dbForPlatform, $authorization); if ($rule->getAttribute('status', '') === RULE_STATUS_CERTIFICATE_GENERATING) { $publisherForCertificates->enqueue(new \Appwrite\Event\Message\Certificate( diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php index f55405bb48..e8167b44a0 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; @@ -149,11 +148,7 @@ class Create extends Action } } - try { - $rule = $authorization->skip(fn () => $dbForPlatform->createDocument('rules', $rule)); - } catch (Duplicate $e) { - throw new Exception(Exception::RULE_ALREADY_EXISTS); - } + $rule = $this->createRule($rule, $dbForPlatform, $authorization); if ($rule->getAttribute('status', '') === RULE_STATUS_CERTIFICATE_GENERATING) { $publisherForCertificates->enqueue(new \Appwrite\Event\Message\Certificate( diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php index 7da9a11636..ca45d73e13 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php @@ -12,7 +12,6 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; -use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; @@ -142,11 +141,7 @@ class Create extends Action } } - try { - $rule = $authorization->skip(fn () => $dbForPlatform->createDocument('rules', $rule)); - } catch (Duplicate $e) { - throw new Exception(Exception::RULE_ALREADY_EXISTS); - } + $rule = $this->createRule($rule, $dbForPlatform, $authorization); if ($rule->getAttribute('status', '') === RULE_STATUS_CERTIFICATE_GENERATING) { $publisherForCertificates->enqueue(new \Appwrite\Event\Message\Certificate(