Skip to content

Commit

Permalink
New Feature #18178: Add Quota CRUD RPC methods (#2458)
Browse files Browse the repository at this point in the history
  • Loading branch information
edgarrmondragon committed Feb 14, 2023
1 parent 3fb2866 commit f3aa319
Show file tree
Hide file tree
Showing 2 changed files with 373 additions and 0 deletions.
240 changes: 240 additions & 0 deletions application/helpers/remotecontrol/remotecontrol_handle.php
Expand Up @@ -2353,6 +2353,246 @@ public function list_questions($sSessionKey, $iSurveyID, $iGroupID = null, $sLan
}
}

/* Quota specific functions */

/**
* Add a new quota with minimum details
*
* This just tries to create an empty quota with the minimal settings.
*
* Failure status: Invalid session key, No permission, Faulty parameters, Creation Failed result
*
* @access public
* @param string $sSessionKey Auth credentials
* @param int $iSurveyID ID the Quota will belong to
* @param string $sQuotaName The name of the new Quota
* @param int $iLimit Quota limit
* @param bool $bActive Whether quota is active
* @param string $sAction ('terminate', 'confirm_terminate')
* @param bool $bAutoloadURL Whether URL is automatically redirected if quota is triggered
* @param string $sMessage Message to be presented to the user
* @param string $sURL URL to be redirected to after finishing the quota
* @param string $sURLDescription Description of the URL
* @return array|int The id of the new quota - Or status
*/
public function add_quota($sSessionKey, $iSurveyID, $sQuotaName, $iLimit, $bActive = true, $sAction = 'terminate', $bAutoloadURL = false, $sMessage = '', $sURL = '', $sURLDescription = '')
{
if ($this->_checkSessionKey($sSessionKey)) {
$iSurveyID = (int) $iSurveyID;
$iLimit = (int) $iLimit;
$bActive = (bool) $bActive;
$sAction = (string) $sAction;
$bAutoloadURL = (int) $bAutoloadURL;
$sMessage = (string) $sMessage;
$sURL = (string) $sURL;
$sURLDescription = (string) $sURLDescription;

if (Permission::model()->hasSurveyPermission($iSurveyID, 'quotas', 'create')) {
$oSurvey = Survey::model()->findByPk($iSurveyID);
if (!isset($oSurvey)) {
return array('status' => 'Error: Invalid survey ID');
}

if ($iLimit < 0) {
return array('status' => 'Error: Invalid limit');
}

switch ($sAction) {
case 'terminate':
$iAction = Quota::ACTION_TERMINATE;
break;
case 'confirm_terminate':
$iAction = Quota::ACTION_CONFIRM_TERMINATE;
break;
default:
return array('status' => 'Error: Invalid quota action');
}

if ($sMessage == '' && ($sURL != '' || $sURLDescription != '')) {
return array('status' => 'Language-specific URL/description is set but no message is given');
}

$oDB = Yii::app()->db;
$oTransaction = $oDB->beginTransaction();

$oQuota = new Quota();
$oQuota->sid = $iSurveyID;
$oQuota->name = $sQuotaName;
$oQuota->qlimit = $iLimit;
$oQuota->action = $iAction;
$oQuota->active = (int) $bActive;
$oQuota->autoload_url = (int) $bAutoloadURL;

if (!$oQuota->save()) {
return array('status' => 'Creation Failed');
}

if (!$sMessage == '') {
$oQuotaLanguageSetting = new QuotaLanguageSetting();
$oQuotaLanguageSetting->quotals_quota_id = $oQuota->id;
$oQuotaLanguageSetting->quotals_language = $oSurvey->language;
$oQuotaLanguageSetting->quotals_name = $sQuotaName;
$oQuotaLanguageSetting->quotals_message = $sMessage;
$oQuotaLanguageSetting->quotals_url = $sURL;
$oQuotaLanguageSetting->quotals_urldescrip = $sURLDescription;

if (!$oQuotaLanguageSetting->save()) {
$oTransaction->rollback();
return array('status' => 'Creation Failed');
}
}

$oTransaction->commit();
return (int) $oQuota->id;

} else {
return array('status' => 'No permission');
}
} else {
return array('status' => 'Invalid session key');
}
}

/**
* List the quotas in a survey
*
* @access public
* @param string $sSessionKey Auth credentials
* @param int $iSurveyID ID of the Survey containing the quotas
* @return array The list of quotas
*/
public function list_quotas($sSessionKey, $iSurveyID)
{
if ($this->_checkSessionKey($sSessionKey)) {
$iSurveyID = (int) $iSurveyID;
$oSurvey = Survey::model()->findByPk($iSurveyID);
if (!isset($oSurvey)) {
return array('status' => 'Error: Invalid survey ID');
}

if (Permission::model()->hasSurveyPermission($iSurveyID, 'quotas', 'read')) {
$aQuotas = Quota::model()->findAllByAttributes(array('sid' => $iSurveyID));
if (count($aQuotas) == 0) {
return array('status' => 'No quotas found');
}

$aData = array();
foreach ($aQuotas as $oRow) {
$aData[] = array(
'id' => $oRow->id,
'name' => $oRow->name,
'action' => $oRow->action,
'limit' => $oRow->qlimit,
'active' => $oRow->active,
'autoload_url' => $oRow->autoload_url,
);
}
return $aData;
} else {
return array('status' => 'No permission');
}
} else {
return array('status' => 'Invalid session key');
}
}

/**
* Delete a quota
*
* @access public
* @param string $sSessionKey Auth credentials
* @param int $iQuotaID The ID of the quota to be deleted
* @return array|int The ID of the deleted quota or status
*/
public function delete_quota($sSessionKey, $iQuotaID)
{
if ($this->_checkSessionKey($sSessionKey)) {
$iQuotaID = (int) $iQuotaID;
$oQuota = Quota::model()->findByPk($iQuotaID);
if (!isset($oQuota)) {
return array('status' => 'Error: Invalid quota ID');
}

if (Permission::model()->hasSurveyPermission($oQuota->sid, 'quotas', 'delete')) {
$oQuota->deleteQuota(array('id' => $iQuotaID));
return array('status' => 'OK');
} else {
return array('status' => 'No permission');
}
} else {
return array('status' => 'Invalid session key');
}
}

/**
* Get quota attributes (RPC function)
*
* Get properties of a quota
* All internal properties of a quota are available.
* @see \Quota for the list of available properties
*
* Failure status : Invalid quota ID, Invalid session key, No permission, No valid Data
*
* @access public
* @param string $sSessionKey Auth credentials
* @param integer $iQuotaId Quota ID
* @param array|null $aQuotaSettings (optional) The properties to get
* @param string $sLanguage Optional parameter language for multilingual quotas
* @return array
*/
public function get_quota_properties($sSessionKey, $iQuotaId, $aQuotaSettings = null, $sLanguage = null)
{
if ($this->_checkSessionKey($sSessionKey)) {
$iQuotaId = (int) $iQuotaId;
$oQuota = Quota::model()->findByPk($iQuotaId);

if (!isset($oQuota)) {
return array('status' => 'Error: Invalid quota ID');
}

if (Permission::model()->hasSurveyPermission($oQuota->sid, 'quotas', 'read')) {
$iSurveyID = $oQuota->sid;
if (is_null($sLanguage)) {
$sLanguage = Survey::model()->findByPk($iSurveyID)->language;
}

$aBasicDestinationFields = Quota::model()->tableSchema->columnNames;

# Quota Language settings
array_push($aBasicDestinationFields, 'quotals_message');
array_push($aBasicDestinationFields, 'quotals_url');
array_push($aBasicDestinationFields, 'quotals_urldescrip');

if (!empty($aQuotaSettings)) {
$aQuotaSettings = array_intersect($aQuotaSettings, $aBasicDestinationFields);
} else {
$aQuotaSettings = $aBasicDestinationFields;
}

if (empty($aQuotaSettings)) {
return array('status' => 'No valid Data');
}

$aResult = array();
foreach ($aQuotaSettings as $sPropertyName) {
if (isset($oQuota->$sPropertyName)) {
$aResult[$sPropertyName] = $oQuota->$sPropertyName;
} elseif (
isset($oQuota->languagesettings[$sLanguage])
&& isset($oQuota->languagesettings[$sLanguage]->$sPropertyName)
) {
$aResult[$sPropertyName] = $oQuota->languagesettings[$sLanguage]->$sPropertyName;
}
}
return $aResult;
} else {
return array('status' => 'No permission');
}
} else {
return array('status' => self::INVALID_SESSION_KEY);
}
}

/**
* Set quota attributes (RPC function)
*
Expand Down
133 changes: 133 additions & 0 deletions tests/unit/helpers/RemoteControlQuotaTest.php
@@ -0,0 +1,133 @@
<?php

namespace ls\tests;

/**
* Tests for the LimeSurvey remote API Quota methods.
*/
class RemoteControlQuotaTest extends TestBaseClass
{
/**
* @var string
*/
protected static $username = null;

/**
* @var string
*/
protected static $password = null;

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

self::$username = getenv('ADMINUSERNAME');
if (!self::$username) {
self::$username = 'admin';
}

self::$password = getenv('PASSWORD');
if (!self::$password) {
self::$password = 'password';
}
}

/**
* Test the quota RPC methods.
*/
public function testQuota()
{
\Yii::import('application.helpers.remotecontrol.remotecontrol_handle', true);
$dbo = \Yii::app()->getDb();

// Make sure the Authdb is in database (might not be the case if no browser login attempt has been made).
$plugin = \Plugin::model()->findByAttributes(array('name'=>'Authdb'));
if (!$plugin) {
$plugin = new \Plugin();
$plugin->name = 'Authdb';
$plugin->active = 1;
$plugin->save();
} else {
$plugin->active = 1;
$plugin->save();
}
App()->getPluginManager()->loadPlugin('Authdb', $plugin->id);
// Clear login attempts.
$query = sprintf('DELETE FROM {{failed_login_attempts}}');
$dbo->createCommand($query)->execute();


$filename = self::$surveysFolder . '/limesurvey_survey_remote_api_group_language.lss';
self::importSurvey($filename);

// Create handler.
$admin = new \AdminController('dummyid');
$handler = new \remotecontrol_handle($admin);

// Get session key.
$sessionKey = $handler->get_session_key(
self::$username,
self::$password
);
$this->assertNotEquals(['status' => 'Invalid user name or password'], $sessionKey);

// Add quota
$quota_id = $handler->add_quota(
$sessionKey,
self::$surveyId,
'Test quota name',
150,
true,
'confirm_terminate',
true,
'Quota reached',
'https://example.com',
'This is the Quota URL'
);
$this->assertIsNumeric($quota_id, '$quota_id = ' . json_encode($quota_id));

$oQuota = \Quota::model()->findByPk($quota_id);
$this->assertNotEmpty($oQuota, 'Added quota not found');

$this->assertEquals(self::$surveyId, $oQuota->sid);
$this->assertEquals('Test quota name', $oQuota->name);
$this->assertEquals(150, $oQuota->qlimit);
$this->assertEquals(1, $oQuota->active);
$this->assertEquals(2, $oQuota->action);
$this->assertEquals(1, $oQuota->autoload_url);
$this->assertEquals('Quota reached', $oQuota->mainLanguagesetting->quotals_message);
$this->assertEquals('https://example.com', $oQuota->mainLanguagesetting->quotals_url);
$this->assertEquals('This is the Quota URL', $oQuota->mainLanguagesetting->quotals_urldescrip);

// List quotas
$quotas = $handler->list_quotas($sessionKey, self::$surveyId);
$this->assertIsArray($quotas);
$this->assertEquals(1, count($quotas));
$this->assertEquals($quota_id, $quotas[0]['id']);

// Update quota properties
$set_result = $handler->set_quota_properties(
$sessionKey,
$quota_id,
array('qlimit' => 200)
);
$this->assertTrue($set_result['success']);
$this->assertEquals(200, $set_result['message']['qlimit']);

// Get quota properties
$properties = $handler->get_quota_properties($sessionKey, $quota_id);
$this->assertEquals(200, $properties['qlimit']);

// Delete quota
$delete_result = $handler->delete_quota($sessionKey, $quota_id);
$this->assertEquals('OK', $delete_result['status']);

// No quotas
$no_quotas_result = $handler->list_quotas($sessionKey, self::$surveyId);
$this->assertEquals('No quotas found', $no_quotas_result['status']);

// Cleanup
self::$testSurvey->delete();
self::$testSurvey = null;
}
}

0 comments on commit f3aa319

Please sign in to comment.