From b03aa8d6322db25dfd9e8840f23bc210f6c22d9d Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 10 Dec 2025 14:32:04 +0530 Subject: [PATCH 01/18] add: custom senders for cloud. --- src/Appwrite/Event/Mail.php | 51 +++++++++++++++++++++++++ src/Appwrite/Platform/Workers/Mails.php | 8 +++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Event/Mail.php b/src/Appwrite/Event/Mail.php index aaaa148fde..93e1042f7b 100644 --- a/src/Appwrite/Event/Mail.php +++ b/src/Appwrite/Event/Mail.php @@ -16,6 +16,9 @@ class Mail extends Event protected string $bodyTemplate = ''; protected array $attachment = []; + protected string $senderEmail = ''; + protected string $senderName = ''; + public function __construct(protected Publisher $publisher) { parent::__construct($publisher); @@ -400,6 +403,50 @@ class Mail extends Event return $this; } + /** + * Set sender email + * + * @param string $email + * @return self + */ + public function setSenderEmail(string $email): self + { + $this->senderEmail = $email; + return $this; + } + + /** + * Get sender email + * + * @return string + */ + public function getSenderEmail(): string + { + return $this->senderEmail; + } + + /** + * Set sender name + * + * @param string $name + * @return self + */ + public function setSenderName(string $name): self + { + $this->senderName = $name; + return $this; + } + + /** + * Get sender name + * + * @return string + */ + public function getSenderName(): string + { + return $this->senderName; + } + /** * Reset * @@ -415,6 +462,8 @@ class Mail extends Event $this->variables = []; $this->bodyTemplate = ''; $this->attachment = []; + $this->senderEmail = ''; + $this->senderName = ''; return $this; } @@ -436,6 +485,8 @@ class Mail extends Event 'smtp' => $this->smtp, 'variables' => $this->variables, 'attachment' => $this->attachment, + 'senderEmail' => $this->senderEmail, + 'senderName' => $this->senderName, 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) ]; } diff --git a/src/Appwrite/Platform/Workers/Mails.php b/src/Appwrite/Platform/Workers/Mails.php index efca484ebf..959d6e39e5 100644 --- a/src/Appwrite/Platform/Workers/Mails.php +++ b/src/Appwrite/Platform/Workers/Mails.php @@ -152,7 +152,13 @@ class Mails extends Action $replyTo = System::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM); $replyToName = \urldecode(System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server')); - if (!empty($smtp)) { + $senderEmail = $payload['senderEmail'] ?? ''; + $senderName = $payload['senderName'] ?? ''; + + if (!empty($senderEmail)) { + $replyTo = $senderEmail; + $replyToName = $senderName; + } elseif (!empty($smtp)) { $replyTo = !empty($smtp['replyTo']) ? $smtp['replyTo'] : $smtp['senderEmail']; $replyToName = $smtp['senderName']; } From 39aa4c4a9a3ad31c5effc0dcbe552d26d407070f Mon Sep 17 00:00:00 2001 From: Darshan Date: Wed, 10 Dec 2025 15:14:55 +0530 Subject: [PATCH 02/18] add: setfrom. --- src/Appwrite/Platform/Workers/Mails.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Appwrite/Platform/Workers/Mails.php b/src/Appwrite/Platform/Workers/Mails.php index 959d6e39e5..5664628754 100644 --- a/src/Appwrite/Platform/Workers/Mails.php +++ b/src/Appwrite/Platform/Workers/Mails.php @@ -158,6 +158,9 @@ class Mails extends Action if (!empty($senderEmail)) { $replyTo = $senderEmail; $replyToName = $senderName; + + // set again since these can be a diff. + $mail->setFrom($senderEmail, $senderName); } elseif (!empty($smtp)) { $replyTo = !empty($smtp['replyTo']) ? $smtp['replyTo'] : $smtp['senderEmail']; $replyToName = $smtp['senderName']; From 90fb5b6321effea3ff082bd1690049d24c4e2a4c Mon Sep 17 00:00:00 2001 From: Levi van Noort <73097785+levivannoort@users.noreply.github.com> Date: Fri, 12 Dec 2025 08:42:49 +0100 Subject: [PATCH 03/18] feat: improved reference client ip through _APP_TRUSTED_HEADERS --- .env | 1 + app/config/variables.php | 9 ++++++ src/Appwrite/Utopia/Request.php | 3 ++ tests/e2e/Services/Account/AccountBase.php | 34 ++++++++++++++++++++++ 4 files changed, 47 insertions(+) diff --git a/.env b/.env index 55ec662f24..c9a8b3a0b4 100644 --- a/.env +++ b/.env @@ -125,3 +125,4 @@ _APP_WEBHOOK_MAX_FAILED_ATTEMPTS=10 _APP_PROJECT_REGIONS=default _APP_FUNCTIONS_CREATION_ABUSE_LIMIT=5000 _APP_STATS_USAGE_DUAL_WRITING_DBS=database_db_main +_APP_TRUSTED_HEADERS= diff --git a/app/config/variables.php b/app/config/variables.php index 408be8d54e..653e959101 100644 --- a/app/config/variables.php +++ b/app/config/variables.php @@ -357,6 +357,15 @@ return [ 'required' => false, 'question' => '', 'filter' => '' + ], + [ + 'name' => '_APP_TRUSTED_HEADERS', + 'description' => 'This option allows you to set the list of trusted headers, the value is a comma‑separated list of HTTP header names, evaluated left-to-right for the first valid IP. Header names are treated case-insensitively.', + 'introduction' => '1.8.0', + 'default' => 'x-forwarded-for', + 'required' => false, + 'question' => '', + 'filter' => '' ] ], ], diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index ce570d2af9..8e6b5d47b3 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -9,9 +9,12 @@ use Swoole\Http\Request as SwooleRequest; use Utopia\Database\Validator\Authorization; use Utopia\Route; use Utopia\Swoole\Request as UtopiaRequest; +use Utopia\System\System; class Request extends UtopiaRequest { + protected array $trustedIpHeaders = explode(",", System::getEnv('_APP_TRUSTED_HEADERS') ?? 'x-forwarded-for'); + /** * @var array */ diff --git a/tests/e2e/Services/Account/AccountBase.php b/tests/e2e/Services/Account/AccountBase.php index 13b5015241..c678fb83cd 100644 --- a/tests/e2e/Services/Account/AccountBase.php +++ b/tests/e2e/Services/Account/AccountBase.php @@ -326,4 +326,38 @@ trait AccountBase $this->assertEquals($response['headers']['status-code'], 204); } + + public function testTrustedIpViaHeaders(): void + { + $email = uniqid() . 'user@localhost.test'; + $password = 'password'; + $name = 'User Name'; + + $response = $this->client->call(Client::METHOD_POST, '/account', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-forwarded-for' => '203.0.113.195', + ]), [ + 'userId' => ID::unique(), + 'email' => $email, + 'password' => $password, + 'name' => $name, + ]); + + $this->assertEquals($response['headers']['status-code'], 201); + + $response = $this->client->call(Client::METHOD_POST, '/account/sessions/email', array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-forwarded-for' => '203.0.113.195', + ]), [ + 'email' => $email, + 'password' => $password, + ]); + + $this->assertEquals($response['headers']['status-code'], 201); + $this->assertEquals('203.0.113.195', $response['body']['clientIp'] ?? $response['body']['ip'] ?? ''); + } } From 2cb86c57efb95de3b86e0d8fdc1444de0e7cf265 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Fri, 12 Dec 2025 09:21:57 +0000 Subject: [PATCH 04/18] fix: preflight requests --- app/init/resources.php | 8 +++++++- tests/e2e/General/HTTPTest.php | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/app/init/resources.php b/app/init/resources.php index 2a2852d4e9..6351dae478 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -198,8 +198,14 @@ App::setResource('allowedHostnames', function (array $platform, Document $projec $allowed[] = $request->getHostname(); } - /* Allow the request origin if a dev key or rule is found */ $originHostname = parse_url($request->getOrigin(), PHP_URL_HOST); + + /* Add request hostname for preflight requests */ + if ($request->getMethod() === 'OPTIONS') { + $allowed[] = $originHostname; + } + + /* Allow the request origin if a dev key or rule is found */ if ((!$rule->isEmpty() || !$devKey->isEmpty()) && !empty($originHostname)) { $allowed[] = $originHostname; } diff --git a/tests/e2e/General/HTTPTest.php b/tests/e2e/General/HTTPTest.php index 35d7ad0919..b8ccde202e 100644 --- a/tests/e2e/General/HTTPTest.php +++ b/tests/e2e/General/HTTPTest.php @@ -184,7 +184,22 @@ class HTTPTest extends Scope 'origin' => 'http://google.com', ]); $this->assertNull($response['headers']['access-control-allow-origin'] ?? null); + } + public function testPreflight() + { + + $endpoint = '/v1/projects'; // Can be any non-404 route + + /** + * Test for SUCCESS + */ + $response = $this->client->call(Client::METHOD_OPTIONS, $endpoint, [ + 'origin' => 'http://random.com', + 'access-control-request-headers' => 'X-Appwrite-Project', + 'access-control-request-method' => 'GET' + ]); + $this->assertEquals('http://random.com', $response['headers']['access-control-allow-origin']); } public function testConsoleRedirect() From 6589c6a7863fc2fbf4a75861d9d14532c3a3a071 Mon Sep 17 00:00:00 2001 From: Levi van Noort <73097785+levivannoort@users.noreply.github.com> Date: Fri, 12 Dec 2025 10:54:09 +0100 Subject: [PATCH 05/18] chore: bump utopia-php/framework to version 0.33.35 --- composer.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index 47a32cf774..e88eb8fe62 100644 --- a/composer.lock +++ b/composer.lock @@ -4264,16 +4264,16 @@ }, { "name": "utopia-php/framework", - "version": "0.33.34", + "version": "0.33.35", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "76def92594c32504ec80eaacdb60ff8fad73c856" + "reference": "82b139fb04f30045db51b0d322224f222da32313" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/76def92594c32504ec80eaacdb60ff8fad73c856", - "reference": "76def92594c32504ec80eaacdb60ff8fad73c856", + "url": "https://api.github.com/repos/utopia-php/http/zipball/82b139fb04f30045db51b0d322224f222da32313", + "reference": "82b139fb04f30045db51b0d322224f222da32313", "shasum": "" }, "require": { @@ -4306,9 +4306,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.34" + "source": "https://github.com/utopia-php/http/tree/0.33.35" }, - "time": "2025-12-08T07:55:31+00:00" + "time": "2025-12-12T08:33:52+00:00" }, { "name": "utopia-php/image", From 205249663503e25e0b15974b777fbbc83f4263fd Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 12 Dec 2025 17:41:00 +0530 Subject: [PATCH 06/18] add: support for replyTo* and simplify variables. --- src/Appwrite/Event/Mail.php | 61 +++++++++++++++++++++---- src/Appwrite/Platform/Workers/Mails.php | 29 ++++++++---- 2 files changed, 71 insertions(+), 19 deletions(-) diff --git a/src/Appwrite/Event/Mail.php b/src/Appwrite/Event/Mail.php index 93e1042f7b..c801d30493 100644 --- a/src/Appwrite/Event/Mail.php +++ b/src/Appwrite/Event/Mail.php @@ -16,8 +16,7 @@ class Mail extends Event protected string $bodyTemplate = ''; protected array $attachment = []; - protected string $senderEmail = ''; - protected string $senderName = ''; + protected array $customMailOptions = []; public function __construct(protected Publisher $publisher) { @@ -411,7 +410,7 @@ class Mail extends Event */ public function setSenderEmail(string $email): self { - $this->senderEmail = $email; + $this->customMailOptions['senderEmail'] = $email; return $this; } @@ -422,7 +421,7 @@ class Mail extends Event */ public function getSenderEmail(): string { - return $this->senderEmail; + return $this->customMailOptions['senderEmail'] ?? ''; } /** @@ -433,7 +432,7 @@ class Mail extends Event */ public function setSenderName(string $name): self { - $this->senderName = $name; + $this->customMailOptions['senderName'] = $name; return $this; } @@ -444,7 +443,51 @@ class Mail extends Event */ public function getSenderName(): string { - return $this->senderName; + return $this->customMailOptions['senderName'] ?? ''; + } + + /** + * Set reply-to email + * + * @param string $email + * @return self + */ + public function setReplyToEmail(string $email): self + { + $this->customMailOptions['replyToEmail'] = $email; + return $this; + } + + /** + * Get reply-to email + * + * @return string + */ + public function getReplyToEmail(): string + { + return $this->customMailOptions['replyToEmail'] ?? ''; + } + + /** + * Set reply-to name + * + * @param string $name + * @return self + */ + public function setReplyToName(string $name): self + { + $this->customMailOptions['replyToName'] = $name; + return $this; + } + + /** + * Get reply-to name + * + * @return string + */ + public function getReplyToName(): string + { + return $this->customMailOptions['replyToName'] ?? ''; } /** @@ -462,8 +505,7 @@ class Mail extends Event $this->variables = []; $this->bodyTemplate = ''; $this->attachment = []; - $this->senderEmail = ''; - $this->senderName = ''; + $this->customMailOptions = []; return $this; } @@ -485,8 +527,7 @@ class Mail extends Event 'smtp' => $this->smtp, 'variables' => $this->variables, 'attachment' => $this->attachment, - 'senderEmail' => $this->senderEmail, - 'senderName' => $this->senderName, + 'customMailOptions' => $this->customMailOptions, 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) ]; } diff --git a/src/Appwrite/Platform/Workers/Mails.php b/src/Appwrite/Platform/Workers/Mails.php index ccc665ad85..20f5d1912e 100644 --- a/src/Appwrite/Platform/Workers/Mails.php +++ b/src/Appwrite/Platform/Workers/Mails.php @@ -152,18 +152,29 @@ class Mails extends Action $replyTo = System::getEnv('_APP_SYSTEM_EMAIL_ADDRESS', APP_EMAIL_TEAM); $replyToName = \urldecode(System::getEnv('_APP_SYSTEM_EMAIL_NAME', APP_NAME . ' Server')); - $senderEmail = $payload['senderEmail'] ?? ''; - $senderName = $payload['senderName'] ?? ''; + $customMailOptions = $payload['customMailOptions'] ?? []; - if (!empty($senderEmail)) { - $replyTo = $senderEmail; - $replyToName = $senderName; + // override sender if custom options are provided. + if (!empty($customMailOptions['senderEmail']) || !empty($customMailOptions['senderName'])) { + // custom email > fallback to default set + $fromEmail = $customMailOptions['senderEmail'] ?? $mail->From; - // set again since these can be a diff. - $mail->setFrom($senderEmail, $senderName); + // custom name > fallback to default set + $fromName = $customMailOptions['senderName'] ?? $mail->FromName; + $mail->setFrom($fromEmail, $fromName); + } + + // override reply-to if custom options provided + if (!empty($customMailOptions['replyToEmail']) || !empty($customMailOptions['replyToName'])) { + // custom reply email > fallback to default set + $replyTo = $customMailOptions['replyToEmail'] ?? $replyTo; + + // custom reply name > fallback to default set + $replyToName = $customMailOptions['replyToName'] ?? $replyToName; } elseif (!empty($smtp)) { - $replyTo = !empty($smtp['replyTo']) ? $smtp['replyTo'] : $smtp['senderEmail']; - $replyToName = $smtp['senderName']; + // new smtp options are available, use them! + $replyTo = !empty($smtp['replyTo']) ? $smtp['replyTo'] : ($smtp['senderEmail'] ?? $replyTo); + $replyToName = $smtp['senderName'] ?? $replyToName; } $mail->addReplyTo($replyTo, $replyToName); From 37b43b0ce08e296592b90736e4b1b4a977bbc048 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 12 Dec 2025 17:49:48 +0530 Subject: [PATCH 07/18] address comment. --- src/Appwrite/Platform/Workers/Mails.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Mails.php b/src/Appwrite/Platform/Workers/Mails.php index 20f5d1912e..01448620f3 100644 --- a/src/Appwrite/Platform/Workers/Mails.php +++ b/src/Appwrite/Platform/Workers/Mails.php @@ -154,25 +154,17 @@ class Mails extends Action $customMailOptions = $payload['customMailOptions'] ?? []; - // override sender if custom options are provided. + // fallback hierarchy: Custom options > SMTP config > Defaults. if (!empty($customMailOptions['senderEmail']) || !empty($customMailOptions['senderName'])) { - // custom email > fallback to default set $fromEmail = $customMailOptions['senderEmail'] ?? $mail->From; - - // custom name > fallback to default set $fromName = $customMailOptions['senderName'] ?? $mail->FromName; $mail->setFrom($fromEmail, $fromName); } - // override reply-to if custom options provided if (!empty($customMailOptions['replyToEmail']) || !empty($customMailOptions['replyToName'])) { - // custom reply email > fallback to default set $replyTo = $customMailOptions['replyToEmail'] ?? $replyTo; - - // custom reply name > fallback to default set $replyToName = $customMailOptions['replyToName'] ?? $replyToName; } elseif (!empty($smtp)) { - // new smtp options are available, use them! $replyTo = !empty($smtp['replyTo']) ? $smtp['replyTo'] : ($smtp['senderEmail'] ?? $replyTo); $replyToName = $smtp['senderName'] ?? $replyToName; } From ce9a54fd4b39b11ec058f218872a734b6d423088 Mon Sep 17 00:00:00 2001 From: Levi van Noort <73097785+levivannoort@users.noreply.github.com> Date: Fri, 12 Dec 2025 15:31:42 +0100 Subject: [PATCH 08/18] chore: change implementation for trustedip --- .env | 2 +- src/Appwrite/Utopia/Request.php | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.env b/.env index c9a8b3a0b4..9c6dc04223 100644 --- a/.env +++ b/.env @@ -125,4 +125,4 @@ _APP_WEBHOOK_MAX_FAILED_ATTEMPTS=10 _APP_PROJECT_REGIONS=default _APP_FUNCTIONS_CREATION_ABUSE_LIMIT=5000 _APP_STATS_USAGE_DUAL_WRITING_DBS=database_db_main -_APP_TRUSTED_HEADERS= +_APP_TRUSTED_HEADERS=x-forwarded-for diff --git a/src/Appwrite/Utopia/Request.php b/src/Appwrite/Utopia/Request.php index 8e6b5d47b3..cb449e6ffa 100644 --- a/src/Appwrite/Utopia/Request.php +++ b/src/Appwrite/Utopia/Request.php @@ -13,8 +13,6 @@ use Utopia\System\System; class Request extends UtopiaRequest { - protected array $trustedIpHeaders = explode(",", System::getEnv('_APP_TRUSTED_HEADERS') ?? 'x-forwarded-for'); - /** * @var array */ @@ -23,6 +21,9 @@ class Request extends UtopiaRequest public function __construct(SwooleRequest $request) { + $trustedHeaders = System::getEnv('_APP_TRUSTED_HEADERS', 'x-forwarded-for'); + $this->setTrustedIpHeaders(explode(',', $trustedHeaders)); + parent::__construct($request); } From 45d5f14b83c45704405520b6a5c1d927055d3da8 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 13 Dec 2025 16:43:19 +0530 Subject: [PATCH 09/18] add: targets. --- .github/workflows/publish.yml | 1 + .github/workflows/release.yml | 5 +++-- Dockerfile | 31 +++++++++++++++++++++---------- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index c78156ca04..180eb5428d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -42,6 +42,7 @@ jobs: with: context: . platforms: linux/amd64,linux/arm64 + target: production build-args: | VERSION=${{ steps.meta.outputs.version }} VITE_APPWRITE_GROWTH_ENDPOINT=https://growth.appwrite.io/v1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 862d669466..5426f53583 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,10 +20,10 @@ jobs: submodules: recursive - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Login to Docker Hub uses: docker/login-action@v2 @@ -46,6 +46,7 @@ jobs: with: context: . platforms: linux/amd64,linux/arm64 + target: production build-args: | VERSION=${{ steps.meta.outputs.version }} push: true diff --git a/Dockerfile b/Dockerfile index e932297671..d082d9c81f 100755 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ RUN composer install --ignore-platform-reqs --optimize-autoloader \ --no-plugins --no-scripts --prefer-dist \ `if [ "$TESTING" != "true" ]; then echo "--no-dev"; fi` -FROM appwrite/base:0.10.6 AS final +FROM appwrite/base:0.10.6 AS base LABEL maintainer="team@appwrite.io" @@ -36,9 +36,7 @@ COPY --from=composer /usr/local/src/vendor /usr/src/code/vendor COPY ./app /usr/src/code/app COPY ./public /usr/src/code/public COPY ./bin /usr/local/bin -COPY ./docs /usr/src/code/docs COPY ./src /usr/src/code/src -COPY ./dev /usr/src/code/dev # Set Volumes RUN mkdir -p /storage/uploads && \ @@ -90,15 +88,28 @@ RUN chmod +x /usr/local/bin/doctor && \ chmod +x /usr/local/bin/stats-resources && \ chmod +x /usr/local/bin/worker-stats-resources -# Letsencrypt Permissions RUN mkdir -p /etc/letsencrypt/live/ && chmod -Rf 755 /etc/letsencrypt/live/ -# Enable Extensions -RUN if [ "$DEBUG" = "true" ]; then cp /usr/src/code/dev/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini; fi -RUN if [ "$DEBUG" = "true" ]; then mkdir -p /tmp/xdebug; fi -RUN if [ "$DEBUG" = "true" ]; then apk add --update --no-cache openssh-client github-cli; fi -RUN if [ "$DEBUG" = "false" ]; then rm -rf /usr/src/code/dev; fi -RUN if [ "$DEBUG" = "false" ]; then rm -f /usr/local/lib/php/extensions/no-debug-non-zts-20230831/xdebug.so; fi +FROM base AS production + +RUN rm -rf /usr/src/code/app/config/specs && \ + rm -f /usr/local/lib/php/extensions/no-debug-non-zts-20240924/xdebug.so && \ + find /usr -name '*.a' -delete 2>/dev/null || true && \ + find /usr -type d -name '__pycache__' -exec rm -rf {} + 2>/dev/null || true && \ + find /usr -name '*.pyc' -delete 2>/dev/null || true + +EXPOSE 80 + +CMD [ "php", "app/http.php" ] + +FROM base AS development + +COPY ./docs /usr/src/code/docs +COPY ./dev /usr/src/code/dev + +RUN cp /usr/src/code/dev/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini && \ + mkdir -p /tmp/xdebug && \ + apk add --update --no-cache openssh-client github-cli EXPOSE 80 From f3f3ac80f8f3e8de546adf9aaf4278a965648663 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sat, 13 Dec 2025 18:59:12 +0530 Subject: [PATCH 10/18] fix: tests. --- Dockerfile | 6 ++++-- docker-compose.yml | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index d082d9c81f..e146008222 100755 --- a/Dockerfile +++ b/Dockerfile @@ -107,9 +107,11 @@ FROM base AS development COPY ./docs /usr/src/code/docs COPY ./dev /usr/src/code/dev -RUN cp /usr/src/code/dev/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini && \ +RUN if [ "$DEBUG" = "true" ]; then \ + cp /usr/src/code/dev/xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini && \ mkdir -p /tmp/xdebug && \ - apk add --update --no-cache openssh-client github-cli + apk add --update --no-cache openssh-client github-cli; \ + fi EXPOSE 80 diff --git a/docker-compose.yml b/docker-compose.yml index f246dbb456..87b45d7e4f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -54,6 +54,7 @@ services: image: appwrite-dev build: context: . + target: development args: DEBUG: false TESTING: true From da0b2a751757055902e5595d7d7d71bb5ebd4967 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Sun, 14 Dec 2025 22:41:15 +0000 Subject: [PATCH 11/18] fix: cors wildcard --- src/Appwrite/Network/Cors.php | 5 ++++- tests/unit/Network/CorsTest.php | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Network/Cors.php b/src/Appwrite/Network/Cors.php index 88d0158379..9fc47c5808 100644 --- a/src/Appwrite/Network/Cors.php +++ b/src/Appwrite/Network/Cors.php @@ -2,6 +2,8 @@ namespace Appwrite\Network; +use Utopia\Validator\Hostname; + /** * Generate CORS response headers for an incoming request. * @@ -76,7 +78,8 @@ final class Cors } // Match only by host - if (!\in_array($host, $this->allowedHosts, true)) { + $validator = new Hostname($this->allowedHosts); + if (!$validator->isValid($host)) { return $headers; } diff --git a/tests/unit/Network/CorsTest.php b/tests/unit/Network/CorsTest.php index 521bf21f1e..986e48ebb5 100644 --- a/tests/unit/Network/CorsTest.php +++ b/tests/unit/Network/CorsTest.php @@ -36,6 +36,21 @@ final class CorsTest extends TestCase $this->assertSame('https://foo.com', $result[Cors::HEADER_ALLOW_ORIGIN]); } + public function testSubdomainWildcardAllowsAnySubdomain(): void + { + $cors = new Cors( + allowedHosts: ['*.example.com'], + allowedMethods: ['GET'], + allowedHeaders: ['X-Test'], + exposedHeaders: [], + allowCredentials: false + ); + + $result = $cors->headers('https://foo.example.com'); + + $this->assertSame('https://foo.example.com', $result[Cors::HEADER_ALLOW_ORIGIN]); + } + public function testEmptyOriginReturnsStaticHeadersOnly(): void { $cors = new Cors( From cd90974e1597e0f58991895063f9a3162ce57f97 Mon Sep 17 00:00:00 2001 From: Levi van Noort <73097785+levivannoort@users.noreply.github.com> Date: Mon, 15 Dec 2025 13:22:29 +0100 Subject: [PATCH 12/18] chore: changes to test to validate default behaviour instead --- .env | 2 +- composer.json | 2 +- composer.lock | 22 ++++++++++++---------- docker-compose.yml | 1 + tests/e2e/Services/Account/AccountBase.php | 11 +++++++---- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/.env b/.env index 9c6dc04223..5343c8d086 100644 --- a/.env +++ b/.env @@ -125,4 +125,4 @@ _APP_WEBHOOK_MAX_FAILED_ATTEMPTS=10 _APP_PROJECT_REGIONS=default _APP_FUNCTIONS_CREATION_ABUSE_LIMIT=5000 _APP_STATS_USAGE_DUAL_WRITING_DBS=database_db_main -_APP_TRUSTED_HEADERS=x-forwarded-for +_APP_TRUSTED_HEADERS= \ No newline at end of file diff --git a/composer.json b/composer.json index d32b739311..d898378ca4 100644 --- a/composer.json +++ b/composer.json @@ -72,7 +72,7 @@ "utopia-php/queue": "0.11.*", "utopia-php/registry": "0.5.*", "utopia-php/storage": "0.18.*", - "utopia-php/swoole": "0.8.*", + "utopia-php/swoole": "clo-3704-duplicate-changes-to-swoole-due-to-overwrite-dev", "utopia-php/system": "0.9.*", "utopia-php/telemetry": "0.1.*", "utopia-php/vcs": "0.13.*", diff --git a/composer.lock b/composer.lock index e88eb8fe62..656b8a4267 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": "7c9cb03eb5267f1e7a3ffc037ae22b6a", + "content-hash": "28bb3cab7ab0efd5e6abf9fa923bd17b", "packages": [ { "name": "adhocore/jwt", @@ -5011,22 +5011,22 @@ }, { "name": "utopia-php/swoole", - "version": "0.8.4", + "version": "dev-clo-3704-duplicate-changes-to-swoole-due-to-overwrite", "source": { "type": "git", "url": "https://github.com/utopia-php/swoole.git", - "reference": "150c30700e738c52348cce9ed0e0f0ff96872081" + "reference": "af6911b0a4eef4b7a825cd246e6070b02b856b8f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/swoole/zipball/150c30700e738c52348cce9ed0e0f0ff96872081", - "reference": "150c30700e738c52348cce9ed0e0f0ff96872081", + "url": "https://api.github.com/repos/utopia-php/swoole/zipball/af6911b0a4eef4b7a825cd246e6070b02b856b8f", + "reference": "af6911b0a4eef4b7a825cd246e6070b02b856b8f", "shasum": "" }, "require": { "ext-swoole": "*", "php": ">=8.0", - "utopia-php/framework": "0.33.*" + "utopia-php/framework": "0.33.x" }, "require-dev": { "laravel/pint": "1.2.*", @@ -5056,9 +5056,9 @@ ], "support": { "issues": "https://github.com/utopia-php/swoole/issues", - "source": "https://github.com/utopia-php/swoole/tree/0.8.4" + "source": "https://github.com/utopia-php/swoole/tree/clo-3704-duplicate-changes-to-swoole-due-to-overwrite" }, - "time": "2025-09-07T09:39:46+00:00" + "time": "2025-12-15T10:03:28+00:00" }, { "name": "utopia-php/system", @@ -8943,7 +8943,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "utopia-php/swoole": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8967,5 +8969,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/docker-compose.yml b/docker-compose.yml index f246dbb456..ac1c7cd0f1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -219,6 +219,7 @@ services: - _APP_DATABASE_SHARED_NAMESPACE - _APP_FUNCTIONS_CREATION_ABUSE_LIMIT - _APP_CUSTOM_DOMAIN_DENY_LIST + - _APP_TRUSTED_HEADERS extra_hosts: - "host.docker.internal:host-gateway" diff --git a/tests/e2e/Services/Account/AccountBase.php b/tests/e2e/Services/Account/AccountBase.php index c678fb83cd..0c9d481371 100644 --- a/tests/e2e/Services/Account/AccountBase.php +++ b/tests/e2e/Services/Account/AccountBase.php @@ -327,17 +327,20 @@ trait AccountBase $this->assertEquals($response['headers']['status-code'], 204); } - public function testTrustedIpViaHeaders(): void + public function testFallbackForTrustedIp(): void { $email = uniqid() . 'user@localhost.test'; $password = 'password'; $name = 'User Name'; + // call appwrite directly to avoid proxy stripping the headers + $this->client->setEndpoint('http://localhost/v1'); + $response = $this->client->call(Client::METHOD_POST, '/account', array_merge([ 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-forwarded-for' => '203.0.113.195', + 'x-forwarded-for' => '191.0.113.195', ]), [ 'userId' => ID::unique(), 'email' => $email, @@ -351,13 +354,13 @@ trait AccountBase 'origin' => 'http://localhost', 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], - 'x-forwarded-for' => '203.0.113.195', + 'x-forwarded-for' => '191.0.113.195', ]), [ 'email' => $email, 'password' => $password, ]); $this->assertEquals($response['headers']['status-code'], 201); - $this->assertEquals('203.0.113.195', $response['body']['clientIp'] ?? $response['body']['ip'] ?? ''); + $this->assertEquals('191.0.113.195', $response['body']['clientIp'] ?? $response['body']['ip'] ?? ''); } } From 0d7eb88a45da31c8cb7c9d4950e0f7a0619c5f34 Mon Sep 17 00:00:00 2001 From: Levi van Noort <73097785+levivannoort@users.noreply.github.com> Date: Mon, 15 Dec 2025 15:08:23 +0100 Subject: [PATCH 13/18] chore: update utopia-php/swoole to version 0.8.5 --- composer.json | 2 +- composer.lock | 20 +++++++++----------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/composer.json b/composer.json index d898378ca4..95d10ca0c9 100644 --- a/composer.json +++ b/composer.json @@ -72,7 +72,7 @@ "utopia-php/queue": "0.11.*", "utopia-php/registry": "0.5.*", "utopia-php/storage": "0.18.*", - "utopia-php/swoole": "clo-3704-duplicate-changes-to-swoole-due-to-overwrite-dev", + "utopia-php/swoole": "0.8.5", "utopia-php/system": "0.9.*", "utopia-php/telemetry": "0.1.*", "utopia-php/vcs": "0.13.*", diff --git a/composer.lock b/composer.lock index 656b8a4267..47488ae924 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": "28bb3cab7ab0efd5e6abf9fa923bd17b", + "content-hash": "3be93acc5ee72f38f6e3436487169976", "packages": [ { "name": "adhocore/jwt", @@ -5011,22 +5011,22 @@ }, { "name": "utopia-php/swoole", - "version": "dev-clo-3704-duplicate-changes-to-swoole-due-to-overwrite", + "version": "0.8.5", "source": { "type": "git", "url": "https://github.com/utopia-php/swoole.git", - "reference": "af6911b0a4eef4b7a825cd246e6070b02b856b8f" + "reference": "e42b6b8e44c457a7b35d8a857d7af1d67d667c58" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/swoole/zipball/af6911b0a4eef4b7a825cd246e6070b02b856b8f", - "reference": "af6911b0a4eef4b7a825cd246e6070b02b856b8f", + "url": "https://api.github.com/repos/utopia-php/swoole/zipball/e42b6b8e44c457a7b35d8a857d7af1d67d667c58", + "reference": "e42b6b8e44c457a7b35d8a857d7af1d67d667c58", "shasum": "" }, "require": { "ext-swoole": "*", "php": ">=8.0", - "utopia-php/framework": "0.33.x" + "utopia-php/framework": "0.33.35" }, "require-dev": { "laravel/pint": "1.2.*", @@ -5056,9 +5056,9 @@ ], "support": { "issues": "https://github.com/utopia-php/swoole/issues", - "source": "https://github.com/utopia-php/swoole/tree/clo-3704-duplicate-changes-to-swoole-due-to-overwrite" + "source": "https://github.com/utopia-php/swoole/tree/0.8.5" }, - "time": "2025-12-15T10:03:28+00:00" + "time": "2025-12-15T14:03:23+00:00" }, { "name": "utopia-php/system", @@ -8943,9 +8943,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/swoole": 20 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From 8a35762843c172c78933b8b493cb62847296ed8e Mon Sep 17 00:00:00 2001 From: Levi van Noort <73097785+levivannoort@users.noreply.github.com> Date: Mon, 15 Dec 2025 15:36:13 +0100 Subject: [PATCH 14/18] chore: update utopia-php/swoole version constraint to 0.8.* --- composer.json | 2 +- composer.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 95d10ca0c9..d32b739311 100644 --- a/composer.json +++ b/composer.json @@ -72,7 +72,7 @@ "utopia-php/queue": "0.11.*", "utopia-php/registry": "0.5.*", "utopia-php/storage": "0.18.*", - "utopia-php/swoole": "0.8.5", + "utopia-php/swoole": "0.8.*", "utopia-php/system": "0.9.*", "utopia-php/telemetry": "0.1.*", "utopia-php/vcs": "0.13.*", diff --git a/composer.lock b/composer.lock index 47488ae924..6277c96145 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": "3be93acc5ee72f38f6e3436487169976", + "content-hash": "7c9cb03eb5267f1e7a3ffc037ae22b6a", "packages": [ { "name": "adhocore/jwt", From 03a19cc83c3fafbd5fab5d016392a2555f578ac0 Mon Sep 17 00:00:00 2001 From: Levi van Noort <73097785+levivannoort@users.noreply.github.com> Date: Mon, 15 Dec 2025 15:49:21 +0100 Subject: [PATCH 15/18] chore: set _APP_TRUSTED_HEADERS to x-forwarded-for --- .env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.env b/.env index 5343c8d086..3a0c4a50cb 100644 --- a/.env +++ b/.env @@ -125,4 +125,4 @@ _APP_WEBHOOK_MAX_FAILED_ATTEMPTS=10 _APP_PROJECT_REGIONS=default _APP_FUNCTIONS_CREATION_ABUSE_LIMIT=5000 _APP_STATS_USAGE_DUAL_WRITING_DBS=database_db_main -_APP_TRUSTED_HEADERS= \ No newline at end of file +_APP_TRUSTED_HEADERS=x-forwarded-for \ No newline at end of file From 7e6846f8f81320ec7f6cd9b02273a6f0e807cd33 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 15 Dec 2025 15:01:26 +0000 Subject: [PATCH 16/18] fix: platform defaults --- src/Appwrite/Event/Build.php | 8 +++++++- src/Appwrite/Event/Func.php | 8 +++++++- src/Appwrite/Event/Mail.php | 9 ++++++++- src/Appwrite/Event/Migration.php | 8 +++++++- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Event/Build.php b/src/Appwrite/Event/Build.php index 79437c3e58..38f423829e 100644 --- a/src/Appwrite/Event/Build.php +++ b/src/Appwrite/Event/Build.php @@ -2,6 +2,7 @@ namespace Appwrite\Event; +use Utopia\Config\Config; use Utopia\Database\Document; use Utopia\Queue\Publisher; @@ -110,13 +111,18 @@ class Build extends Event */ protected function preparePayload(): array { + $platform = $this->platform; + if (empty($platform)) { + $platform = Config::getParam('platform', []); + } + return [ 'project' => $this->project, 'resource' => $this->resource, 'deployment' => $this->deployment, 'type' => $this->type, 'template' => $this->template, - 'platform' => $this->platform + 'platform' => $platform, ]; } diff --git a/src/Appwrite/Event/Func.php b/src/Appwrite/Event/Func.php index 380a28f1db..c9622a9ce0 100644 --- a/src/Appwrite/Event/Func.php +++ b/src/Appwrite/Event/Func.php @@ -2,6 +2,7 @@ namespace Appwrite\Event; +use Utopia\Config\Config; use Utopia\Database\Document; use Utopia\Queue\Publisher; @@ -202,6 +203,11 @@ class Func extends Event { $events = $this->getEvent() ? Event::generateEvents($this->getEvent(), $this->getParams()) : null; + $platform = $this->platform; + if (empty($platform)) { + $platform = Config::getParam('platform', []); + } + return [ 'project' => $this->project, 'user' => $this->user, @@ -217,7 +223,7 @@ class Func extends Event 'path' => $this->path, 'headers' => $this->headers, 'method' => $this->method, - 'platform' => $this->platform + 'platform' => $platform, ]; } } diff --git a/src/Appwrite/Event/Mail.php b/src/Appwrite/Event/Mail.php index c801d30493..ed96f6f93a 100644 --- a/src/Appwrite/Event/Mail.php +++ b/src/Appwrite/Event/Mail.php @@ -2,6 +2,7 @@ namespace Appwrite\Event; +use Utopia\Config\Config; use Utopia\Queue\Publisher; class Mail extends Event @@ -516,6 +517,11 @@ class Mail extends Event */ protected function preparePayload(): array { + $platform = $this->platform; + if (empty($platform)) { + $platform = Config::getParam('platform', []); + } + return [ 'project' => $this->project, 'recipient' => $this->recipient, @@ -528,7 +534,8 @@ class Mail extends Event 'variables' => $this->variables, 'attachment' => $this->attachment, 'customMailOptions' => $this->customMailOptions, - 'events' => Event::generateEvents($this->getEvent(), $this->getParams()) + 'events' => Event::generateEvents($this->getEvent(), $this->getParams()), + 'platform' => $platform, ]; } } diff --git a/src/Appwrite/Event/Migration.php b/src/Appwrite/Event/Migration.php index ca54310ce6..a224d4f4c3 100644 --- a/src/Appwrite/Event/Migration.php +++ b/src/Appwrite/Event/Migration.php @@ -2,6 +2,7 @@ namespace Appwrite\Event; +use Utopia\Config\Config; use Utopia\Database\Document; use Utopia\Queue\Publisher; @@ -73,11 +74,16 @@ class Migration extends Event */ protected function preparePayload(): array { + $platform = $this->platform; + if (empty($platform)) { + $platform = Config::getParam('platform', []); + } + return [ 'project' => $this->project, 'user' => $this->user, 'migration' => $this->migration, - 'platform' => $this->platform, + 'platform' => $platform, ]; } } From 4b58e1a85e86278386084d6aa4e671beec25c650 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 15 Dec 2025 16:55:48 +0000 Subject: [PATCH 17/18] revert: backups endpoints --- app/controllers/shared/api.php | 1 - src/Appwrite/Platform/Workers/Migrations.php | 10 +++------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 8467468ed6..83b56f626a 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -628,7 +628,6 @@ App::init() $queueForFunctions->setPlatform($platform); $queueForBuilds->setPlatform($platform); $queueForMails->setPlatform($platform); - $queueForMigrations->setPlatform($platform); // Clone the queues, to prevent events triggered by the database listener // from overwriting the events that are supposed to be triggered in the shutdown hook. diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index a10ddc4904..e7b12c5d9d 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -52,8 +52,6 @@ class Migrations extends Action protected array $plan; - protected array $platform; - /** * @var array */ @@ -108,7 +106,6 @@ class Migrations extends Action $this->deviceForMigrations = $deviceForMigrations; $this->deviceForFiles = $deviceForFiles; $this->plan = $plan; - $this->platform = $payload['platform'] ?? []; if (empty($payload)) { throw new Exception('Missing payload'); @@ -144,7 +141,6 @@ class Migrations extends Action $credentials = $migration->getAttribute('credentials'); $migrationOptions = $migration->getAttribute('options'); $dataSource = Appwrite::SOURCE_API; - $endpoint = $this->platform['endpoint'] ?: ($credentials['endpoint'] ?? 'http://appwrite.test/v1'); $database = null; $queries = []; @@ -178,7 +174,7 @@ class Migrations extends Action ), SourceAppwrite::getName() => new SourceAppwrite( $credentials['projectId'], - $endpoint, + $credentials['endpoint'] === 'http://localhost/v1' ? 'http://appwrite/v1' : $credentials['endpoint'], $credentials['apiKey'], $dataSource, $database, @@ -209,7 +205,7 @@ class Migrations extends Action return match ($destination) { DestinationAppwrite::getName() => new DestinationAppwrite( $this->project->getId(), - $this->platform['endpoint'], + 'http://appwrite/v1', $apiKey, $this->dbForProject, Config::getParam('collections', [])['databases']['collections'], @@ -313,7 +309,7 @@ class Migrations extends Action ) { $credentials = $migration->getAttribute('credentials', []); $credentials['projectId'] = $credentials['projectId'] ?? $project->getId(); - $credentials['endpoint'] = $credentials['endpoint'] ?? $this->platform['endpoint']; + $credentials['endpoint'] = $credentials['endpoint'] ?? 'http://appwrite/v1'; $credentials['apiKey'] = $credentials['apiKey'] ?? $tempAPIKey; $migration->setAttribute('credentials', $credentials); } From e931938b7855d59d8d24704f7d457b17aeb432ea Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 15 Dec 2025 18:01:30 +0000 Subject: [PATCH 18/18] revert: backups endpoints --- docker-compose.yml | 1 + src/Appwrite/Platform/Workers/Migrations.php | 22 +++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 80fb99c0fd..f18bb747b8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -737,6 +737,7 @@ services: - _APP_MIGRATIONS_FIREBASE_CLIENT_ID - _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET - _APP_DATABASE_SHARED_TABLES + - _APP_OPTIONS_FORCE_HTTPS appwrite-task-maintenance: entrypoint: maintenance diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index e7b12c5d9d..69c78d9620 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -144,6 +144,12 @@ class Migrations extends Action $database = null; $queries = []; + if ($credentials['endpoint'] === 'http://localhost/v1') { + $platform = Config::getParam('platform', []); + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; + $credentials['endpoint'] = $protocol . '://' . $platform['apiHostname'] . '/v1'; + } + if ($source === Appwrite::getName() && $destination === DestinationCSV::getName()) { $dataSource = Appwrite::SOURCE_DATABASE; $database = $this->dbForProject; @@ -174,7 +180,7 @@ class Migrations extends Action ), SourceAppwrite::getName() => new SourceAppwrite( $credentials['projectId'], - $credentials['endpoint'] === 'http://localhost/v1' ? 'http://appwrite/v1' : $credentials['endpoint'], + $credentials['endpoint'], $credentials['apiKey'], $dataSource, $database, @@ -202,10 +208,13 @@ class Migrations extends Action $destination = $migration->getAttribute('destination'); $options = $migration->getAttribute('options', []); + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; + $platform = Config::getParam('platform', []); + return match ($destination) { DestinationAppwrite::getName() => new DestinationAppwrite( $this->project->getId(), - 'http://appwrite/v1', + $protocol . '://' . $platform['apiHostname'] . '/v1', $apiKey, $this->dbForProject, Config::getParam('collections', [])['databases']['collections'], @@ -302,6 +311,8 @@ class Migrations extends Action $transfer = $source = $destination = null; + + try { if ( $migration->getAttribute('source') === SourceAppwrite::getName() && @@ -309,8 +320,13 @@ class Migrations extends Action ) { $credentials = $migration->getAttribute('credentials', []); $credentials['projectId'] = $credentials['projectId'] ?? $project->getId(); - $credentials['endpoint'] = $credentials['endpoint'] ?? 'http://appwrite/v1'; $credentials['apiKey'] = $credentials['apiKey'] ?? $tempAPIKey; + + if (empty($credentials['endpoint'])) { + $platform = Config::getParam('platform', []); + $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') === 'disabled' ? 'http' : 'https'; + $credentials['endpoint'] = $protocol . '://' . $platform['apiHostname'] . '/v1'; + } $migration->setAttribute('credentials', $credentials); }