mirror of
https://github.com/appwrite/appwrite.git
synced 2026-05-26 13:51:13 +00:00
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
This commit is contained in:
+8
-8
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace Appwrite\Platform\Modules\Project\Http\Project\Templates\Email;
|
||||
namespace Appwrite\Platform\Modules\Console\Http\Templates\Email;
|
||||
|
||||
use Appwrite\SDK\AuthType;
|
||||
use Appwrite\SDK\Method;
|
||||
@@ -15,28 +15,28 @@ use Utopia\Platform\Scope\HTTP;
|
||||
use Utopia\System\System;
|
||||
use Utopia\Validator\WhiteList;
|
||||
|
||||
class GetDefault extends Action
|
||||
class Get extends Action
|
||||
{
|
||||
use HTTP;
|
||||
|
||||
public static function getName()
|
||||
public static function getName(): string
|
||||
{
|
||||
return 'getDefaultProjectEmailTemplate';
|
||||
return 'getConsoleEmailTemplate';
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->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: <<<EOT
|
||||
Get the Appwrite built-in default email template for the specified type and locale. Always returns the unmodified default, ignoring any custom overrides.
|
||||
Get the Appwrite built-in default email template for the specified type and locale. Always returns the unmodified default, ignoring any custom project overrides.
|
||||
EOT,
|
||||
auth: [AuthType::ADMIN, AuthType::KEY],
|
||||
responses: [
|
||||
@@ -17,6 +17,7 @@ use Appwrite\Platform\Modules\Console\Http\Redirects\Root\Get as RedirectRoot;
|
||||
use Appwrite\Platform\Modules\Console\Http\Resources\Get as GetResourceAvailability;
|
||||
use Appwrite\Platform\Modules\Console\Http\Scopes\Organization\XList as ListOrganizationScopes;
|
||||
use Appwrite\Platform\Modules\Console\Http\Scopes\Project\XList as ListKeyScopes;
|
||||
use Appwrite\Platform\Modules\Console\Http\Templates\Email\Get as GetEmailTemplate;
|
||||
use Appwrite\Platform\Modules\Console\Http\Variables\Get as GetVariables;
|
||||
use Utopia\Platform\Service;
|
||||
|
||||
@@ -31,6 +32,7 @@ class Http extends Service
|
||||
$this->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());
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user