Skip to content

Commit

Permalink
Mail: Validate Mustache templates
Browse files Browse the repository at this point in the history
  • Loading branch information
mjansenDatabay committed Oct 31, 2023
1 parent 434b718 commit 0d6186c
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 5 deletions.
5 changes: 4 additions & 1 deletion Services/Mail/classes/Service/MailService.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ public function __construct(protected Container $dic)
{
if (!isset($this->dic[ilMailTemplateServiceInterface::class])) {
$this->dic[ilMailTemplateServiceInterface::class] = static function (Container $c): ilMailTemplateServiceInterface {
return new ilMailTemplateService(new ilMailTemplateRepository($c->database()));
return new ilMailTemplateService(
new ilMailTemplateRepository($c->database()),
$c->mail()->mustacheFactory()
);
};
}
}
Expand Down
27 changes: 27 additions & 0 deletions Services/Mail/classes/Templates/TemplateMessageSyntaxException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/**
* This file is part of ILIAS, a powerful learning management system
* published by ILIAS open source e-Learning e.V.
*
* ILIAS is licensed with the GPL-3.0,
* see https://www.gnu.org/licenses/gpl-3.0.en.html
* You should have received a copy of said license along with the
* source code, too.
*
* If this is not the case or you just want to try ILIAS, you'll find
* us at:
* https://www.ilias.de
* https://github.com/ILIAS-eLearning
*
*********************************************************************/

declare(strict_types=1);

namespace ILIAS\Mail\Templates;

use ilException;

class TemplateMessageSyntaxException extends ilException
{
}
27 changes: 27 additions & 0 deletions Services/Mail/classes/Templates/TemplateSubjectSyntaxException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

/**
* This file is part of ILIAS, a powerful learning management system
* published by ILIAS open source e-Learning e.V.
*
* ILIAS is licensed with the GPL-3.0,
* see https://www.gnu.org/licenses/gpl-3.0.en.html
* You should have received a copy of said license along with the
* source code, too.
*
* If this is not the case or you just want to try ILIAS, you'll find
* us at:
* https://www.ilias.de
* https://github.com/ILIAS-eLearning
*
*********************************************************************/

declare(strict_types=1);

namespace ILIAS\Mail\Templates;

use ilException;

class TemplateSubjectSyntaxException extends ilException
{
}
10 changes: 10 additions & 0 deletions Services/Mail/classes/class.ilMailTemplateGUI.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@ protected function insertTemplate(): void

$this->tpl->setOnScreenMessage('success', $this->lng->txt('saved_successfully'), true);
$this->ctrl->redirect($this, 'showTemplates');
} catch (\ILIAS\Mail\Templates\TemplateSubjectSyntaxException) {
$form->getItemByPostVar('m_subject')->setAlert($this->lng->txt('mail_template_invalid_tpl_syntax'));
$this->tpl->setOnScreenMessage('failure', $this->lng->txt('form_input_not_valid'));
} catch (\ILIAS\Mail\Templates\TemplateMessageSyntaxException) {
$form->getItemByPostVar('m_message')->setAlert($this->lng->txt('mail_template_invalid_tpl_syntax'));
$this->tpl->setOnScreenMessage('failure', $this->lng->txt('form_input_not_valid'));
} catch (Exception) {
$form->getItemByPostVar('context')->setAlert(
$this->lng->txt('mail_template_no_valid_context')
Expand Down Expand Up @@ -222,6 +228,10 @@ protected function updateTemplate(): void
$this->ctrl->redirect($this, 'showTemplates');
} catch (OutOfBoundsException) {
$this->tpl->setOnScreenMessage('failure', $this->lng->txt('mail_template_missing_id'));
} catch (\ILIAS\Mail\Templates\TemplateSubjectSyntaxException) {
$form->getItemByPostVar('m_subject')->setAlert($this->lng->txt('mail_template_invalid_tpl_syntax'));
} catch (\ILIAS\Mail\Templates\TemplateMessageSyntaxException) {
$form->getItemByPostVar('m_message')->setAlert($this->lng->txt('mail_template_invalid_tpl_syntax'));
} catch (Exception) {
$form->getItemByPostVar('context')->setAlert(
$this->lng->txt('mail_template_no_valid_context')
Expand Down
33 changes: 31 additions & 2 deletions Services/Mail/classes/class.ilMailTemplateService.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@

declare(strict_types=1);

use ILIAS\Mail\Templates\TemplateSubjectSyntaxException;
use ILIAS\Mail\Templates\TemplateMessageSyntaxException;

class ilMailTemplateService implements ilMailTemplateServiceInterface
{
public function __construct(protected ilMailTemplateRepository $repository)
{
public function __construct(
protected ilMailTemplateRepository $repository,
protected ilMustacheFactory $mustacheFactory
) {
}

public function createNewTemplate(
Expand All @@ -31,6 +36,18 @@ public function createNewTemplate(
string $message,
string $language
): ilMailTemplate {
try {
$this->mustacheFactory->getBasicEngine()->render($subject, []);
} catch (Exception) {
throw new TemplateSubjectSyntaxException('Invalid mail template for subject');
}

try {
$this->mustacheFactory->getBasicEngine()->render($message, []);
} catch (Exception) {
throw new TemplateMessageSyntaxException('Invalid mail template for message');
}

$template = new ilMailTemplate();
$template->setContext($contextId);
$template->setTitle($title);
Expand All @@ -51,6 +68,18 @@ public function modifyExistingTemplate(
string $message,
string $language
): void {
try {
$this->mustacheFactory->getBasicEngine()->render($subject, []);
} catch (Exception) {
throw new TemplateSubjectSyntaxException('Invalid mail template for subject');
}

try {
$this->mustacheFactory->getBasicEngine()->render($message, []);
} catch (Exception) {
throw new TemplateMessageSyntaxException('Invalid mail template for message');
}

$template = $this->repository->findById($templateId);

$template->setContext($contextId);
Expand Down
29 changes: 29 additions & 0 deletions Services/Mail/classes/class.ilObjMailGUI.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class ilObjMailGUI extends ilObjectGUI
private const PASSWORD_PLACE_HOLDER = '***********************';

private readonly ilTabsGUI $tabs;
private readonly ilMustacheFactory $mustache_factory;

public function __construct($a_data, int $a_id, bool $a_call_by_reference)
{
Expand All @@ -40,6 +41,7 @@ public function __construct($a_data, int $a_id, bool $a_call_by_reference)
parent::__construct($a_data, $a_id, $a_call_by_reference, false);

$this->tabs = $DIC->tabs();
$this->mustache_factory = $DIC->mail()->mustacheFactory();

$this->lng->loadLanguageModule('mail');
}
Expand Down Expand Up @@ -634,6 +636,33 @@ protected function saveExternalSettingsFormObject(): void
return;
}

// If all forms in ILIAS use the UI/KS forms (here and in Services/Mail), we should move this to a propert constraint/trafo
$is_valid_template_syntax = $this->refinery->custom()->constraint(function ($value): bool {
try {
$this->mustache_factory->getBasicEngine()->render((string) $value, []);
return true;
} catch (Exception) {
return false;
}
}, $this->lng->txt('mail_template_invalid_tpl_syntax'));

$valid_templates = true;
foreach (['mail_system_usr_from_name', 'mail_system_sys_signature'] as $template) {
try {
$is_valid_template_syntax->check((string) $form->getInput($template));
} catch (Exception) {
$form->getItemByPostVar($template)->setAlert(
$is_valid_template_syntax->problemWith((string) $form->getInput($template))
);
$valid_templates = false;
}
}
if (!$valid_templates) {
$form->setValuesByPost();
$this->showExternalSettingsFormObject($form);
return;
}

$this->settings->set('mail_smtp_status', (string) ((int) $form->getInput('mail_smtp_status')));
$this->settings->set('mail_smtp_host', (string) $form->getInput('mail_smtp_host'));
$this->settings->set('mail_smtp_port', (string) ((int) $form->getInput('mail_smtp_port')));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@

declare(strict_types=1);

use ILIAS\Mail\Templates\TemplateSubjectSyntaxException;
use ILIAS\Mail\Templates\TemplateMessageSyntaxException;

interface ilMailTemplateServiceInterface
{
public function createNewTemplate(
Expand All @@ -28,6 +31,9 @@ public function createNewTemplate(
string $language
): ilMailTemplate;

/**
* @throws TemplateSubjectSyntaxException|TemplateMessageSyntaxException
*/
public function modifyExistingTemplate(
int $templateId,
string $contextId,
Expand Down
6 changes: 4 additions & 2 deletions Services/Mail/test/ilMailTemplateServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ public function testDefaultTemplateCanBeSetByContext(): void

$repo->expects($this->once())->method('findByContextId')->with($template->getContext())->willReturn($all);
$repo->expects($this->exactly(count($all)))->method('store');
$service = new ilMailTemplateService($repo);
$mustache_factory = $this->getMockBuilder(ilMustacheFactory::class)->getMock();
$service = new ilMailTemplateService($repo, $mustache_factory);

$service->setAsContextDefault($template);

Expand All @@ -74,7 +75,8 @@ public function testDefaultTemplateForContextCanBeUnset(): void
$template->setContext('phpunit');

$repo->expects($this->once())->method('store')->with($template);
$service = new ilMailTemplateService($repo);
$mustache_factory = $this->getMockBuilder(ilMustacheFactory::class)->getMock();
$service = new ilMailTemplateService($repo, $mustache_factory);

$service->unsetAsContextDefault($template);

Expand Down
1 change: 1 addition & 0 deletions lang/ilias_de.lang
Original file line number Diff line number Diff line change
Expand Up @@ -11391,6 +11391,7 @@ mail#:#mail_template_client#:#Textvorlage
mail#:#mail_template_client_info#:#Wählen Sie zwischen einer der verfügbaren Textvorlagen. Sie haben die Möglichkeit, die durch die Textvorlage angebotenen Platzhalter zu nutzen. Bei der Wahl einer Textvorlage werden Nachricht und Betreff in diesem Formular (falls in der Vorlage definiert) ersetzt.
mail#:#mail_template_context#:#Kontext
mail#:#mail_template_default#:# (Standard)
mail#:#mail_template_invalid_tpl_syntax#:#Es wurde eine ungültige Syntax festgestellt. Bitte prüfen Sie Ihre Eingaben, vor allem hinsichtlich der Platzhalter-Syntax.
mail#:#mail_template_missing_id#:#Die Aktion kann nicht ausgeführt werden, da die ID der Textvorlage nicht korrekt übertragen wurde.
mail#:#mail_template_no_context_available#:#Aktuell wird von keinem ILIAS-Service oder -Modul ein Kontext bereitgestellt. Das Anlegen oder Bearbeiten von Textvorlagen ist daher nicht möglich.
mail#:#mail_template_no_valid_context#:#Der gewählte Kontext ist nicht gültig.
Expand Down
1 change: 1 addition & 0 deletions lang/ilias_en.lang
Original file line number Diff line number Diff line change
Expand Up @@ -11380,6 +11380,7 @@ mail#:#mail_template_client#:#Text Template
mail#:#mail_template_client_info#:#Choose one of the available text templates and make use of it's placeholders. If you choose a text template, body and subject of this form (if defined in the text template) will be replaced.
mail#:#mail_template_context#:#Context
mail#:#mail_template_default#:# (Default)
mail#:#mail_template_invalid_tpl_syntax#:#An invalid syntax has been detected. Please ensure a valid input, especially regarding the placeholder syntax.
mail#:#mail_template_missing_id#:#Can't execute the action because the text template id is missing.
mail#:#mail_template_no_context_available#:#There is no context provided by any ILIAS service or module. Thus it is not possible to create or edit a text template.
mail#:#mail_template_no_valid_context#:#The given context is not valid.
Expand Down

0 comments on commit 0d6186c

Please sign in to comment.