diff --git a/app/config/errors.php b/app/config/errors.php index 0ad10f4f7..635750c87 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -524,6 +524,11 @@ return [ 'description' => 'The project key has expired. Please generate a new key using the Appwrite console.', 'code' => 401, ], + Exception::PROJECT_DEFAULT_TEMPLATE_DELETION => [ + 'name' => Exception::PROJECT_DEFAULT_TEMPLATE_DELETION, + 'description' => 'The default template for the project cannot be deleted.', + 'code' => 401, + ], Exception::WEBHOOK_NOT_FOUND => [ 'name' => Exception::WEBHOOK_NOT_FOUND, 'description' => 'Webhook with the requested ID could not be found.', diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 02f2ee411..6325c5f51 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -739,7 +739,7 @@ App::post('/v1/account/sessions/magic-url') $smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false; $customTemplate = $project->getAttribute('templates', [])['email.magicSession-' . $locale->default] ?? []; - if($smtpEnabled && !empty($customTemplate)) { + if ($smtpEnabled && !empty($customTemplate)) { $body = $customTemplate['message']; $subject = $customTemplate['subject']; $from = $customTemplate['senderName']; @@ -1009,9 +1009,9 @@ App::post('/v1/account/sessions/phone') $dbForProject->deleteCachedDocument('users', $user->getId()); $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); - + $customTemplate = $project->getAttribute('templates', [])['sms.login-' . $locale->default] ?? []; - if(!empty($customTemplate)) { + if (!empty($customTemplate)) { $message = $customTemplate['message']; } @@ -2114,7 +2114,7 @@ App::post('/v1/account/recovery') $smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false; $customTemplate = $project->getAttribute('templates', [])['email.recovery-' . $locale->default] ?? []; - if($smtpEnabled && !empty($customTemplate)) { + if ($smtpEnabled && !empty($customTemplate)) { $body = $customTemplate['message']; $subject = $customTemplate['subject']; $from = $customTemplate['senderName']; @@ -2306,7 +2306,7 @@ App::post('/v1/account/verification') $smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false; $customTemplate = $project->getAttribute('templates', [])['email.verification-' . $locale->default] ?? []; - if($smtpEnabled && !empty($customTemplate)) { + if ($smtpEnabled && !empty($customTemplate)) { $body = $customTemplate['message']; $subject = $customTemplate['subject']; $from = $customTemplate['senderName']; @@ -2483,7 +2483,7 @@ App::post('/v1/account/verification/phone') $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); $customTemplate = $project->getAttribute('templates', [])['sms.verification-' . $locale->default] ?? []; - if(!empty($customTemplate)) { + if (!empty($customTemplate)) { $message = $customTemplate['message']; } diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 062e300fd..92dcfd711 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -1815,3 +1815,89 @@ App::get('/v1/projects/:projectId/templates/email/:type/:locale') $response->dynamic(new Document($template), Response::MODEL_EMAIL_TEMPLATE); }); + +App::DELETE('/v1/projects/:projectId/templates/sms/:type/:locale') + ->desc('Reset custom SMS template') + ->groups(['api', 'projects']) + ->label('scope', 'projects.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'projects') + ->label('sdk.method', 'getSmsTemplate') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_SMS_TEMPLATE) + ->param('projectId', '', new UID(), 'Project unique ID.') + ->param('type', '', new WhiteList(Config::getParam('locale-templates')['sms'] ?? []), 'Template type') + ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->inject('response') + ->inject('dbForConsole') + ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { + + $project = $dbForConsole->getDocument('projects', $projectId); + + if ($project->isEmpty()) { + throw new Exception(Exception::PROJECT_NOT_FOUND); + } + + $templates = $project->getAttribute('templates', []); + $template = $templates['sms.' . $type . '-' . $locale] ?? null; + + if (is_null($template)) { + throw new Exception(Exception::PROJECT_DEFAULT_TEMPLATE_DELETION); + } + + unset($template['sms.' . $type . '-' . $locale]); + + $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); + + $response->dynamic(new Document([ + 'type' => $type, + 'locale' => $locale, + 'message' => $template['message'] + ]), Response::MODEL_SMS_TEMPLATE); + }); + +App::DELETE('/v1/projects/:projectId/templates/email/:type/:locale') + ->desc('Reset custom email template') + ->groups(['api', 'projects']) + ->label('scope', 'projects.write') + ->label('sdk.auth', [APP_AUTH_TYPE_ADMIN]) + ->label('sdk.namespace', 'projects') + ->label('sdk.method', 'getEmailTemplate') + ->label('sdk.response.code', Response::STATUS_CODE_OK) + ->label('sdk.response.type', Response::CONTENT_TYPE_JSON) + ->label('sdk.response.model', Response::MODEL_EMAIL_TEMPLATE) + ->param('projectId', '', new UID(), 'Project unique ID.') + ->param('type', '', new WhiteList(Config::getParam('locale-templates')['email'] ?? []), 'Template type') + ->param('locale', '', fn($localeCodes) => new WhiteList($localeCodes), 'Template locale', false, ['localeCodes']) + ->inject('response') + ->inject('dbForConsole') + ->action(function (string $projectId, string $type, string $locale, Response $response, Database $dbForConsole) { + + $project = $dbForConsole->getDocument('projects', $projectId); + + if ($project->isEmpty()) { + throw new Exception(Exception::PROJECT_NOT_FOUND); + } + + $templates = $project->getAttribute('templates', []); + $template = $templates['email.' . $type . '-' . $locale] ?? null; + + if (is_null($template)) { + throw new Exception(Exception::PROJECT_DEFAULT_TEMPLATE_DELETION); + } + + unset($templates['email.' . $type . '-' . $locale]); + + $project = $dbForConsole->updateDocument('projects', $project->getId(), $project->setAttribute('templates', $templates)); + + $response->dynamic(new Document([ + 'type' => $type, + 'locale' => $locale, + 'senderName' => $template['senderName'], + 'senderEmail' => $template['senderEmail'], + 'subject' => $template['subject'], + 'replyTo' => $template['replyTo'], + 'message' => $template['message'] + ]), Response::MODEL_EMAIL_TEMPLATE); + }); diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 02d832b52..3743a45bf 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -545,7 +545,7 @@ App::post('/v1/teams/:teamId/memberships') $smtpEnabled = $project->getAttribute('smtp', [])['enabled'] ?? false; $customTemplate = $project->getAttribute('templates', [])['email.invitation-' . $locale->default] ?? []; - if($smtpEnabled && !empty($customTemplate)) { + if ($smtpEnabled && !empty($customTemplate)) { $body = $customTemplate['message']; $subject = $customTemplate['subject']; $from = $customTemplate['senderName']; @@ -583,7 +583,7 @@ App::post('/v1/teams/:teamId/memberships') $message = Template::fromFile(__DIR__ . '/../../config/locale/templates/sms-base.tpl'); $customTemplate = $project->getAttribute('templates', [])['sms.invitation-' . $locale->default] ?? []; - if(!empty($customTemplate)) { + if (!empty($customTemplate)) { $message = $customTemplate['message']; } diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 411ab6e85..af65bc952 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -164,6 +164,8 @@ class Exception extends \Exception public const PROJECT_RESERVED_PROJECT = 'project_reserved_project'; public const PROJECT_KEY_EXPIRED = 'project_key_expired'; + public const PROJECT_DEFAULT_TEMPLATE_DELETION = 'project_default_template_deletion'; + /** Webhooks */ public const WEBHOOK_NOT_FOUND = 'webhook_not_found';