Skip to content

Commit

Permalink
Fixed issue #18436: RC API - Inviting members with invalid language s… (
Browse files Browse the repository at this point in the history
  • Loading branch information
Shnoulle committed Oct 25, 2023
1 parent 34bbdcf commit 5e78af0
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 13 deletions.
17 changes: 13 additions & 4 deletions application/helpers/admin/token_helper.php
Expand Up @@ -55,6 +55,7 @@ function emailTokens($iSurveyID, $aResultTokens, $sType, $continueOnError = fals
'name' => $aTokenRow["firstname"] . " " . $aTokenRow["lastname"],
'email' => $aTokenRow["email"],
'status' => 'fail',
'warning' => null,
'error' => 'Token not valid anymore'
);
if ($continueOnError) {
Expand All @@ -64,27 +65,35 @@ function emailTokens($iSurveyID, $aResultTokens, $sType, $continueOnError = fals
}
}
if ($mail->sendMessage()) {
$warnings = null;
$oToken = Token::model($iSurveyID)->findByPk($aTokenRow['tid']);
if ($sType == 'invite' || $sType == 'register') {
$oToken->sent = dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i", Yii::app()->getConfig("timeadjust"));
$oToken->save();
if (!$oToken->save(true, ['sent'])) {
$warnings = $oToken->getErrors();
}
}
if ($sType == 'remind') {
$oToken->remindersent = dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i", Yii::app()->getConfig("timeadjust"));
$oToken->remindercount++;
$oToken->save();
if (!$oToken->save(true, ['remindersent', 'remindercount'])) {
$warnings = $oToken->getErrors();
}
}
$aResult[$aTokenRow['tid']] = array(
'name' => $aTokenRow["firstname"] . " " . $aTokenRow["lastname"],
'email' => $aTokenRow["email"],
'status' => 'OK'
'status' => 'OK',
'warning' => $warnings,
'error' => null,
);
} else {
$aResult[$aTokenRow['tid']] = array(
'name' => $aTokenRow["firstname"] . " " . $aTokenRow["lastname"],
'email' => $aTokenRow["email"],
'status' => 'fail',
'error' => $mail->getError(),
'warning' => null,
'error' => $mail->getError()
);
}
}
Expand Down
5 changes: 3 additions & 2 deletions application/helpers/remotecontrol/remotecontrol_handle.php
Expand Up @@ -2647,7 +2647,7 @@ public function mail_registered_participants($sSessionKey, $iSurveyID, $override
$iSurveyID = (int) $iSurveyID;
$oSurvey = Survey::model()->findByPk($iSurveyID);
if (!isset($oSurvey)) {
return array('status' => 'Error: Invalid survey ID');
return array('status' => 'Error: Invalid survey ID');
}

if (Permission::model()->hasSurveyPermission($iSurveyID, 'tokens', 'update')) {
Expand Down Expand Up @@ -2682,12 +2682,13 @@ public function mail_registered_participants($sSessionKey, $iSurveyID, $override
$aResultTokens = Token::model($iSurveyID)->findAll($command);

if (empty($aResultTokens)) {
return array('status' => 'Error: No candidate tokens');
return array('status' => 'Error: No candidate tokens');
}

foreach ($aResultTokens as $key => $oToken) {
$oToken->decrypt();
//pattern taken from php_filter_validate_email PHP_5_4/ext/filter/logical_filters.c
/* @todo : use LimeMailer::validateAddresses */
$pattern = '/^(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){255,})(?!(?:(?:\\x22?\\x5C[\\x00-\\x7E]\\x22?)|(?:\\x22?[^\\x5C\\x22]\\x22?)){65,}@)(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22))(?:\\.(?:(?:[\\x21\\x23-\\x27\\x2A\\x2B\\x2D\\x2F-\\x39\\x3D\\x3F\\x5E-\\x7E]+)|(?:\\x22(?:[\\x01-\\x08\\x0B\\x0C\\x0E-\\x1F\\x21\\x23-\\x5B\\x5D-\\x7F]|(?:\\x5C[\\x00-\\x7F]))*\\x22)))*@(?:(?:(?!.*[^.]{64,})(?:(?:(?:xn--)?[a-z0-9]+(?:-+[a-z0-9]+)*\\.){1,126}){1,}(?:(?:[a-z][a-z0-9]*)|(?:(?:xn--)[a-z0-9]+))(?:-+[a-z0-9]+)*)|(?:\\[(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){7})|(?:(?!(?:.*[a-f0-9][:\\]]){7,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,5})?)))|(?:(?:IPv6:(?:(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){5}:)|(?:(?!(?:.*[a-f0-9]:){5,})(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3})?::(?:[a-f0-9]{1,4}(?::[a-f0-9]{1,4}){0,3}:)?)))?(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))(?:\\.(?:(?:25[0-5])|(?:2[0-4][0-9])|(?:1[0-9]{2})|(?:[1-9]?[0-9]))){3}))\\]))$/iD';

//pattern to split in case of multiple emails for a participant
Expand Down
33 changes: 29 additions & 4 deletions tests/TestBaseClass.php
Expand Up @@ -183,7 +183,7 @@ public static function deActivatePlugin($pluginName)
public static function dispatchPluginEvent($pluginName, $eventName, $eventValues)
{
$oEvent = (new \PluginEvent($eventName));
foreach($eventValues as $key => $value) {
foreach ($eventValues as $key => $value) {
$oEvent->set($key, $value);
}
\Yii::app()->getPluginManager()->dispatchEvent($oEvent, $pluginName);
Expand All @@ -200,10 +200,10 @@ protected static function createUserWithPermissions(array $userData, array $perm
$oUser = new \User();
$oUser->setAttributes($userData);

if(!$oUser->save()) {
throw new Exception(
if (!$oUser->save()) {
throw new Exception(
"Could not save user: "
.print_r($oUser->getErrors(),true)
. print_r($oUser->getErrors(), true)
);
};

Expand Down Expand Up @@ -257,4 +257,29 @@ protected static function addUserPermissions(int $userId, array $permissions)
}
return $results;
}

/**
* @param string $pluginName
* @return iPlugin
*/
protected static function loadTestPlugin($pluginName)
{
require_once self::$dataFolder . "/plugins/{$pluginName}.php";
$plugin = \Plugin::model()->findByAttributes(['name' => $pluginName]);
if (!$plugin) {
$plugin = new \Plugin();
$plugin->name = $pluginName;
$plugin->active = 1;
$plugin->save();
} else {
$plugin->active = 1;
$plugin->save();
}

$plugin = App()->getPluginManager()->loadPlugin($pluginName, $plugin->id);
if (is_null($plugin)) {
throw new Exception(sprintf('Failed to load test plugin %s', $pluginName));
}
return $plugin;
}
}
36 changes: 36 additions & 0 deletions tests/data/plugins/DummyMailer.php
@@ -0,0 +1,36 @@
<?php

class DummyMailer extends PluginBase
{
protected static $description = 'Marks all emails as sent';
protected static $name = 'DummyMailer';

private $errorToReturn = null;

/** @inheritdoc, this plugin didn't have any public method */
public $allowedPublicMethods = array();

public function init()
{
$this->subscribe('beforeEmail', 'beforeEmail');
$this->subscribe('beforeSurveyEmail', 'beforeEmail');
$this->subscribe('beforeTokenEmail', 'beforeEmail');
}

public function beforeEmail()
{
$event = $this->getEvent();
$event->set('send', false);
$event->set('error', $this->errorToReturn);
}

public function setError($error)
{
$this->errorToReturn = $error;
}

public function reset()
{
$this->errorToReturn = null;
}
}
64 changes: 61 additions & 3 deletions tests/unit/helpers/remotecontrol/InviteParticipantsTest.php
Expand Up @@ -4,10 +4,16 @@

class InviteParticipantsTest extends BaseTest
{
/** @var \DummyMailer */
private static $plugin;

public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();

// Load plugin
self::$plugin = self::loadTestPlugin('DummyMailer');

/**
* Import survey with five participants. Participant 3 is invalid (validuntil in the past)
*/
Expand All @@ -28,20 +34,72 @@ public function testInviteParticipants()
// Assert email sending stopped on error
$this->assertArrayNotHasKey(4, $result);
$this->assertArrayNotHasKey(5, $result);

//Test invitation status in database.
$participant_1 = \Token::model(self::$surveyId)->findByAttributes(array('tid' => 1));
$this->assertNotSame('N', $participant_1->sent, 'Sent field in database should be a date, not ' . $participant_1->sent);

$participant_2 = \Token::model(self::$surveyId)->findByAttributes(array('tid' => 2));
$this->assertNotSame('N', $participant_2->sent, 'Sent field in database should be a date, not ' . $participant_2->sent);

$participant_3 = \Token::model(self::$surveyId)->findByAttributes(array('tid' => 3));
$this->assertSame('N', $participant_3->sent, 'Sent field in database should be N not ' . $participant_3->sent);

$participant_4 = \Token::model(self::$surveyId)->findByAttributes(array('tid' => 4));
$this->assertSame('N', $participant_4->sent, 'Sent field in database should be N, not ' . $participant_4->sent);

$participant_5 = \Token::model(self::$surveyId)->findByAttributes(array('tid' => 4));
$this->assertSame('N', $participant_5->sent, 'Sent field in database should be N, not ' . $participant_5->sent);
}

public function testInviteParticipantsSkippingErrors()
{
$sessionKey = $this->handler->get_session_key($this->getUsername(), $this->getPassword());
$result = $this->handler->invite_participants($sessionKey, self::$surveyId, null, true, true);
// Assert emails for participants 1 and 2 were sent
$this->assertParticipantResultIsOk($result, 1);
$this->assertParticipantResultIsOk($result, 2);
// Assert emails for participants 1 and 2 were not sent
// since they were sent in the previous test.
$this->assertArrayNotHasKey(1, $result);
$this->assertArrayNotHasKey(2, $result);
// Assert email for participant 3 was not sent
$this->assertParticipantResultIsNotOk($result, 3);
// Assert emails for participants 4 and 5 were sent
$this->assertParticipantResultIsOk($result, 4);
$this->assertParticipantResultIsOk($result, 5);

//Test invitation status in database.
$participant_1 = \Token::model(self::$surveyId)->findByAttributes(array('tid' => 1));
$this->assertNotSame('N', $participant_1->sent, 'Sent field in database should be a date, not ' . $participant_1->sent);

$participant_2 = \Token::model(self::$surveyId)->findByAttributes(array('tid' => 2));
$this->assertNotSame('N', $participant_2->sent, 'Sent field in database should be a date, not ' . $participant_2->sent);

$participant_3 = \Token::model(self::$surveyId)->findByAttributes(array('tid' => 3));
$this->assertSame('N', $participant_3->sent, 'Sent field in database should be N not ' . $participant_3->sent);

$participant_4 = \Token::model(self::$surveyId)->findByAttributes(array('tid' => 4));
$this->assertNotSame('N', $participant_4->sent, 'Sent field in database should be a date, not ' . $participant_4->sent);

$participant_5 = \Token::model(self::$surveyId)->findByAttributes(array('tid' => 5));
$this->assertNotSame('N', $participant_5->sent, 'Sent field in database should be a date, not ' . $participant_5->sent);
}

public function testAddNewParticipantWithoutALanguageAndInviteIt()
{
$sessionKey = $this->handler->get_session_key($this->getUsername(), $this->getPassword());

$newParticpants = array(
array(
'firstname' => 'Participant 6',
'email' => 'participant6@example.com',
)
);

$participantsData = $this->handler->add_participants($sessionKey, self::$surveyId, $newParticpants);
$tid = (int)$participantsData[0]['tid'];

$result = $this->handler->invite_participants($sessionKey, self::$surveyId, null, true, true);

$this->assertParticipantResultIsOk($result, $tid);
}

/**
Expand Down

0 comments on commit 5e78af0

Please sign in to comment.