From a614afe5c7ff4536e7d5dbdb4e89803e2fad9118 Mon Sep 17 00:00:00 2001 From: harsh mahajan Date: Fri, 15 May 2026 18:03:12 +0530 Subject: [PATCH] refactor: move email template defaults to console module and add tests - Move GetDefault endpoint to Console module as Get.php (GET /v1/console/templates/email/:templateId, console.getEmailTemplate) - Remove from Project module - Add e2e tests for console.getEmailTemplate and reset=true --- .../Http/Templates/Email/Get.php} | 16 +-- .../Modules/Console/Services/Http.php | 2 + .../Modules/Project/Services/Http.php | 2 - tests/e2e/Services/Project/TemplatesBase.php | 136 ++++++++++++++++++ 4 files changed, 146 insertions(+), 10 deletions(-) rename src/Appwrite/Platform/Modules/{Project/Http/Project/Templates/Email/GetDefault.php => Console/Http/Templates/Email/Get.php} (91%) diff --git a/src/Appwrite/Platform/Modules/Project/Http/Project/Templates/Email/GetDefault.php b/src/Appwrite/Platform/Modules/Console/Http/Templates/Email/Get.php similarity index 91% rename from src/Appwrite/Platform/Modules/Project/Http/Project/Templates/Email/GetDefault.php rename to src/Appwrite/Platform/Modules/Console/Http/Templates/Email/Get.php index c89c39e0d6..97d48603df 100644 --- a/src/Appwrite/Platform/Modules/Project/Http/Project/Templates/Email/GetDefault.php +++ b/src/Appwrite/Platform/Modules/Console/Http/Templates/Email/Get.php @@ -1,6 +1,6 @@ setHttpMethod(Action::HTTP_REQUEST_METHOD_GET) ->setHttpPath('/v1/console/templates/email/:templateId') - ->desc('Get default project email template') - ->groups(['api', 'project']) - ->label('scope', 'templates.read') + ->desc('Get email template') + ->groups(['api', 'projects']) + ->label('scope', 'projects.read') ->label('sdk', new Method( namespace: 'console', group: 'templates', name: 'getEmailTemplate', description: <<addAction(Web::getName(), new Web()); $this->addAction(GetVariables::getName(), new GetVariables()); + $this->addAction(GetEmailTemplate::getName(), new GetEmailTemplate()); $this->addAction(ListOAuth2Providers::getName(), new ListOAuth2Providers()); $this->addAction(ListKeyScopes::getName(), new ListKeyScopes()); $this->addAction(ListOrganizationScopes::getName(), new ListOrganizationScopes()); diff --git a/src/Appwrite/Platform/Modules/Project/Services/Http.php b/src/Appwrite/Platform/Modules/Project/Services/Http.php index 4357f38f4b..3fe9f63d9e 100644 --- a/src/Appwrite/Platform/Modules/Project/Services/Http.php +++ b/src/Appwrite/Platform/Modules/Project/Services/Http.php @@ -91,7 +91,6 @@ use Appwrite\Platform\Modules\Project\Http\Project\Services\Update as UpdateProj use Appwrite\Platform\Modules\Project\Http\Project\SMTP\Tests\Create as CreateSMTPTest; use Appwrite\Platform\Modules\Project\Http\Project\SMTP\Update as UpdateSMTP; use Appwrite\Platform\Modules\Project\Http\Project\Templates\Email\Get as GetTemplate; -use Appwrite\Platform\Modules\Project\Http\Project\Templates\Email\GetDefault as DefaultTemplate; use Appwrite\Platform\Modules\Project\Http\Project\Templates\Email\Update as UpdateTemplate; use Appwrite\Platform\Modules\Project\Http\Project\Templates\Email\XList as ListTemplates; use Appwrite\Platform\Modules\Project\Http\Project\Variables\Create as CreateVariable; @@ -125,7 +124,6 @@ class Http extends Service $this->addAction(ListTemplates::getName(), new ListTemplates()); $this->addAction(GetTemplate::getName(), new GetTemplate()); $this->addAction(UpdateTemplate::getName(), new UpdateTemplate()); - $this->addAction(DefaultTemplate::getName(), new DefaultTemplate()); // Variables $this->addAction(CreateVariable::getName(), new CreateVariable()); diff --git a/tests/e2e/Services/Project/TemplatesBase.php b/tests/e2e/Services/Project/TemplatesBase.php index b240c945b3..a1e46debe7 100644 --- a/tests/e2e/Services/Project/TemplatesBase.php +++ b/tests/e2e/Services/Project/TemplatesBase.php @@ -1147,6 +1147,142 @@ trait TemplatesBase return $this->client->call(Client::METHOD_PATCH, '/project/templates/email', $headers, $params); } + // Console email template (default) tests + + public function testGetConsoleEmailTemplate(): void + { + $response = $this->getConsoleEmailTemplate('verification', 'en'); + + $this->assertSame(200, $response['headers']['status-code']); + $this->assertSame('verification', $response['body']['templateId']); + $this->assertSame('en', $response['body']['locale']); + $this->assertNotEmpty($response['body']['subject']); + $this->assertNotEmpty($response['body']['message']); + $this->assertSame('', $response['body']['senderName']); + $this->assertSame('', $response['body']['senderEmail']); + $this->assertSame('', $response['body']['replyToEmail']); + $this->assertSame('', $response['body']['replyToName']); + } + + public function testGetConsoleEmailTemplateIgnoresCustomOverride(): void + { + $this->ensureSMTPEnabled(); + + // Set a custom override on the project template. + $this->updateEmailTemplate( + templateId: 'recovery', + locale: 'en', + subject: 'Custom subject', + message: 'Custom message', + senderName: 'Custom Sender', + senderEmail: 'custom@appwrite.io', + ); + + // Console endpoint must always return the built-in default, not the override. + $response = $this->getConsoleEmailTemplate('recovery', 'en'); + + $this->assertSame(200, $response['headers']['status-code']); + $this->assertSame('recovery', $response['body']['templateId']); + $this->assertNotSame('Custom subject', $response['body']['subject']); + $this->assertSame('', $response['body']['senderName']); + $this->assertSame('', $response['body']['senderEmail']); + } + + public function testGetConsoleEmailTemplateDefaultLocale(): void + { + $response = $this->getConsoleEmailTemplate('magicSession'); + + $this->assertSame(200, $response['headers']['status-code']); + $this->assertSame('en', $response['body']['locale']); + $this->assertNotEmpty($response['body']['subject']); + } + + public function testGetConsoleEmailTemplateAllTypes(): void + { + $types = [ + 'verification', + 'magicSession', + 'recovery', + 'invitation', + 'mfaChallenge', + 'sessionAlert', + 'otpSession', + ]; + + foreach ($types as $type) { + $response = $this->getConsoleEmailTemplate($type, 'en'); + $this->assertSame(200, $response['headers']['status-code'], "type={$type}"); + $this->assertNotEmpty($response['body']['subject'], "type={$type} must have subject"); + $this->assertNotEmpty($response['body']['message'], "type={$type} must have message"); + } + } + + public function testResetEmailTemplate(): void + { + $this->ensureSMTPEnabled(); + + // Apply a custom override. + $this->updateEmailTemplate( + templateId: 'invitation', + locale: 'en', + subject: 'Custom invite subject', + message: 'Custom invite message', + senderName: 'Bad Sender', + senderEmail: 'bad@example.com', + ); + + $custom = $this->getEmailTemplate('invitation', 'en'); + $this->assertSame('Custom invite subject', $custom['body']['subject']); + $this->assertSame('Bad Sender', $custom['body']['senderName']); + + // Reset to default. + $response = $this->resetEmailTemplate('invitation', 'en'); + $this->assertSame(200, $response['headers']['status-code']); + $this->assertSame('', $response['body']['senderName']); + $this->assertSame('', $response['body']['senderEmail']); + $this->assertNotSame('Custom invite subject', $response['body']['subject']); + + // Confirm the project template now reflects the default. + $after = $this->getEmailTemplate('invitation', 'en'); + $this->assertSame('', $after['body']['senderName']); + $this->assertSame('', $after['body']['senderEmail']); + } + + public function testResetEmailTemplateWithoutSMTP(): void + { + // Reset must work even without SMTP enabled. + $response = $this->resetEmailTemplate('recovery', 'en'); + $this->assertSame(200, $response['headers']['status-code']); + $this->assertSame('', $response['body']['senderName']); + $this->assertSame('', $response['body']['senderEmail']); + } + + protected function getConsoleEmailTemplate(string $templateId, ?string $locale = null): mixed + { + $params = []; + if ($locale !== null) { + $params['locale'] = $locale; + } + + return $this->client->call(Client::METHOD_GET, '/console/templates/email/' . $templateId, \array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + } + + protected function resetEmailTemplate(string $templateId, ?string $locale = null): mixed + { + $params = ['templateId' => $templateId, 'reset' => true]; + if ($locale !== null) { + $params['locale'] = $locale; + } + + return $this->client->call(Client::METHOD_PATCH, '/project/templates/email', \array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), $params); + } + protected function ensureSMTPEnabled(): void { $this->client->call(