Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Allow to assign a default role to LDAP users #3823

Closed
Closed
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions application/config/version.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
* See COPYRIGHT.php for copyright notices and details.
*/

$config['versionnumber'] = '6.5.2';
$config['versionnumber'] = '6.5.3';
$config['dbversionnumber'] = 623;
$config['buildnumber'] = '';
$config['updatable'] = true;
$config['templateapiversion'] = 3;
$config['assetsversionnumber'] = '30384';
$config['assetsversionnumber'] = '30385';
return $config;
7 changes: 6 additions & 1 deletion application/controllers/SurveyAdministrationController.php
Original file line number Diff line number Diff line change
Expand Up @@ -1799,7 +1799,11 @@ public function actionActivateSurvey()
Yii::app()->loadHelper("admin/activate");
$failedgroupcheck = checkGroup($surveyId);
$failedcheck = checkQuestions($surveyId, $surveyId);
$checkFailed = (isset($failedcheck) && $failedcheck) || (isset($failedgroupcheck) && $failedgroupcheck);
$error = "";
if (!$oSurvey->countTotalQuestions) {
$error = gT("There are no questions in this survey.");
}
$checkFailed = (isset($failedcheck) && $failedcheck) || (isset($failedgroupcheck) && $failedgroupcheck) || !empty($error);
$footerButton = '';
if ($checkFailed) {
//survey can not be activated
Expand All @@ -1808,6 +1812,7 @@ public function actionActivateSurvey()
[
'failedcheck' => $failedcheck,
'failedgroupcheck' => $failedgroupcheck,
'error' => $error,
'surveyid' => $oSurvey->sid
],
true
Expand Down
25 changes: 23 additions & 2 deletions application/controllers/admin/ConditionsAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,28 @@ public function index($subaction, $iSurveyID = null, $gid = null, $qid = null)
}
}


// Previous question parsing ==> building cquestions[] and canswers[]
if ($questionscount > 0) {
$qids = [];
for ($index = 0; $index < count($theserows); $index++) {
if ($theserows[$index]['type'] == "1") {
$qids[] = $theserows[$index]['qid'];
}
}
if (count($qids)) {
$rawQuestions = Question::model()->findAllByPk($qids);
$questions = [];
foreach ($rawQuestions as $rawQuestion) {
$questions[$rawQuestion->qid] = $rawQuestion;
}
for ($index = 0; $index < count($theserows); $index++) {
if ($theserows[$index]['type'] == "1") {
$theserows[$index]['qObject'] = $questions[$theserows[$index]['qid']];
}
}
}

list($cquestions, $canswers) = $this->getCAnswersAndCQuestions($theserows);
} //if questionscount > 0
//END Gather Information for this question
Expand Down Expand Up @@ -1479,14 +1499,15 @@ protected function getCAnswersAndCQuestions(array $theserows)
}
unset($x_axis);
} elseif ($rows['type'] == "1") {
/* Used to get dualscale_headerA and dualscale_headerB */
$attr = QuestionAttribute::model()->getQuestionAttributes($rows['qObject']);
//Dual scale
$aresult = Question::model()->with(array(
'questionl10ns' => array(
'condition' => 'questionl10ns.language = :lang',
'params' => array(':lang' => $this->language)
)))->findAllByAttributes(array('parent_qid' => $rows['qid']), array('order' => 'question_order desc'));
)))->findAllByAttributes(array('parent_qid' => $rows['qid']), array('order' => 'question_order ASC, scale_id ASC'));
foreach ($aresult as $arows) {
$attr = QuestionAttribute::model()->getQuestionAttributes($rows['qid']);
$sLanguage = $this->language;
// dualscale_header are always set, but can be empty
$label1 = empty($attr['dualscale_headerA'][$sLanguage]) ? gT('Scale 1') : $attr['dualscale_headerA'][$sLanguage];
Expand Down
5 changes: 3 additions & 2 deletions application/controllers/admin/globalsettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,10 @@ public function index()
*/
public function showphpinfo()
{
if (!Yii::app()->getConfig('demoMode')) {
phpinfo();
if (Yii::app()->getConfig('demoMode') || !Permission::model()->hasGlobalPermission('superadmin', 'read')) {
throw new CHttpException(403, gT("You do not have permission to access this page."));
}
phpinfo();
}

/**
Expand Down
18 changes: 11 additions & 7 deletions application/core/LSUserIdentity.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
*/
class LSUserIdentity extends CUserIdentity
{

const ERROR_IP_LOCKED_OUT = 98;
const ERROR_UNKNOWN_HANDLER = 99;

Expand Down Expand Up @@ -62,16 +61,11 @@ public function authenticate()
$result->setError(self::ERROR_IP_LOCKED_OUT, $message);
}

// If still ok, continue
/* Plugin action(s) : need a plugin */
if ($result->isValid()) {
if (is_null($this->plugin)) {
$result->setError(self::ERROR_UNKNOWN_HANDLER);
} else {
// Never allow login for non-active users.
$user = User::model()->findByAttributes(array('users_name' => $this->username));
if ($user && (int) $user->user_status === 0) {
throw new CHttpException(403, gT("You do not have permission to access this page."));
}
// Delegate actual authentication to plugin
$authEvent = new PluginEvent('newUserSession', $this); // TODO: rename the plugin function authenticate()
$authEvent->set('identity', $this);
Expand All @@ -85,6 +79,16 @@ public function authenticate()
}
}

/* Check user exist, and can login after plugin actions */
if ($result->isValid()) {
/** @var \User|null */
$user = User::model()->findByAttributes(array('users_name' => $this->username));
if (is_null($user) || !$user->canLogin()) {
// Set the result as invalid if user is not active : no specific message
$result->setError(self::ERROR_USERNAME_INVALID);
}
}
/* All action and test done : finalize */
if ($result->isValid()) {
// Perform postlogin
regenerateCSRFToken();
Expand Down
1 change: 1 addition & 0 deletions application/core/TopbarConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ public static function getSurveyTopbarData($sid)
'sid' => $sid,
'oSurvey' => $oSurvey,
'canactivate' => $canactivate,
'candeactivate' => $hasSurveyActivationPermission,
'expired' => $expired,
'notstarted' => $notstarted,
'context' => $context,
Expand Down
33 changes: 33 additions & 0 deletions application/core/plugins/AuthLDAP/AuthLDAP.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,14 @@ class AuthLDAP extends LimeSurvey\PluginManager\AuthPluginBase
'allowInitialUser' => array(
'type' => 'checkbox',
'label' => 'Allow initial user to login via LDAP',
),
// Need to be defined here otherwise saving does not work
'defaultRole' => array(
'type' => 'select',
'options' => array('none'=>'None'),
tograss marked this conversation as resolved.
Show resolved Hide resolved
'default' => 'none',
'label' => 'Select a default role for all LDAP users',
'help' => 'The role must have the "Use LDAP authentication" permission. Other global permissions are disabled.'
)
);

Expand Down Expand Up @@ -390,13 +398,23 @@ public function newLoginForm()
/**
* Modified getPluginSettings since we have a select box that autosubmits
* and we only want to show the relevant options.
* Also append existing roles as options during runtime.
*
* @param boolean $getValues
* @return array
*/
public function getPluginSettings($getValues = true)
{
$aPluginSettings = parent::getPluginSettings($getValues);
// Dynamically append available roles as options
$roles = $this->api->getRoles();
$roleOptions = array("none"=>'None');
tograss marked this conversation as resolved.
Show resolved Hide resolved
foreach ($roles as $role){
$roleOptions[$role->ptid] = $role->name;
}

$aPluginSettings['defaultRole']['options'] = $roleOptions;

if ($getValues) {
$ldapmode = $aPluginSettings['ldapmode']['current'];
$ldapver = $aPluginSettings['ldapversion']['current'];
Expand Down Expand Up @@ -485,6 +503,7 @@ public function newUserSession()
$bindpwd = $this->get('bindpwd');
$groupsearchbase = $this->get('groupsearchbase');
$groupsearchfilter = $this->get('groupsearchfilter');
$defaultrole = $this->get('defaultRole');

/* Get the conexion, createConnection return an error in array, never return false */
$ldapconn = $this->createConnection();
Expand Down Expand Up @@ -589,6 +608,20 @@ public function newUserSession()
}
}
// If we made it here, authentication was a success and we do have a valid user

// If requested assign role to user
if ($defaultrole !== 'none'){
Shnoulle marked this conversation as resolved.
Show resolved Hide resolved
// Ensure $defaultrole is a valid ptid
// the id can be invalid if the role set as default is deleted and
// the plugin settings are never saved after
$role = $this->api->getRole($defaultrole);
if ($role !== null) {
$this->api->addUserInRole($defaultrole, $user->uid);
}else{
$this->log("Trying to assign a non existend role. Check and save the LDAP Plugin Settings", \CLogger::LEVEL_WARNING);
}
}

$this->pluginManager->dispatchEvent(new PluginEvent('newUserLogin', $this));
/* Set the username as found in LimeSurvey */
$this->setUsername($user->users_name);
Expand Down
2 changes: 1 addition & 1 deletion application/helpers/export_helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ function SPSSGetQuery($iSurveyID, $limit = null, $offset = null)
*/
function buildXMLFromQuery($xmlwriter, $Query, $tagname = '', $excludes = array(), $iSurveyID = 0)
{
$iChunkSize = 3000; // This works even for very large result sets and leaves a minimal memory footprint
$iChunkSize = 1000; // This works even for very large result sets and leaves a minimal memory footprint

preg_match('/\bfrom\b\s*{{(\w+)}}/i', (string) $Query, $MatchResults);
if ($tagname != '') {
Expand Down
8 changes: 0 additions & 8 deletions application/helpers/surveytranslator_helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -841,14 +841,6 @@ function getLanguageData($bOrderByNative = false, $sLanguageCode = 'en')
$supportedLanguages['so']['radixpoint'] = 1;
$supportedLanguages['so']['momentjs'] = null;

// Somali
$supportedLanguages['so']['description'] = gT('Somali');
$supportedLanguages['so']['nativedescription'] = 'Af-Soomaali';
$supportedLanguages['so']['rtl'] = false;
$supportedLanguages['so']['dateformat'] = 9;
$supportedLanguages['so']['radixpoint'] = 1;
$supportedLanguages['so']['momentjs'] = null;

// Spanish
$supportedLanguages['es']['description'] = gT('Spanish');
$supportedLanguages['es']['nativedescription'] = 'Espa&#241;ol';
Expand Down
69 changes: 69 additions & 0 deletions application/libraries/PluginManager/LimesurveyApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,73 @@ public function getUserGroups()
return \UserGroup::model()->findAllAsArray();
}


/**
* Returns an array of all roles / permissiontemplates
*
* @return array
*/
public function getRoles()
{
return \Permissiontemplates::model()->findAllAsArray();
}


/**
* Returns a role / permissiontemplate object by $ptid
* Returns null if the object does not exist
*
* @param int $ptid The role / permissiontemplate ID
* @return \Permissiontemplates|null
*/
public function getRole($ptid)
{
return \Permissiontemplates::model()->findByAttributes(array('ptid' => $ptid));
}


/**
* Adds a new role / permissiontemplate object
* Returns null if the object does not exist
*
* @param string $roleName The name vor the new role
* @param string $description The description of the new role
* @param int $create_by user uid . Default is the admin user (1)
* @return boolean True or false if role was added or not
*/
public function addRole($roleName, $description, $created_by = 1)
{
$roleName = flattenText($roleName, false, true, 'UTF-8', true);
tograss marked this conversation as resolved.
Show resolved Hide resolved
$description = flattenText($description);
if (isset($roleName) && strlen((string) $roleName) > 0) {
$newRole = new \Permissiontemplates();
$newRole->name = $roleName;
$newRole->description = $description;
$newRole->created_by = $created_by;
# @todo formate of date ?
$newRole->created_at = date('Y-m-d H:i:s');
$newRole->renewed_last = date('Y-m-d H:i:s');
return (boolean) $newRole->save();
}else {
throw new InvalidArgumentException('must provide a role name');
}
}

/**
* Adds a role to a User
* @param integer $ptid The ID of the role/ permissiontemplate the user should be added to
* @param integer $uid The Id of the user that should have the new role assigned
*/
public function addUserInRole($ptid, $uid)
{
$role = $this->getRole($ptid);
if ($role !== null ){
return $role -> applyToUser($uid);
}else{
throw new InvalidArgumentException('Ust provide a valid ptid / permissiontemplate can not be found');
}
}

/**
* Returns a UserGroup object by ugid
* Returns null if the object does not exist
Expand All @@ -538,6 +605,8 @@ public function getUserInGroup($ugid, $uid)
return \UserInGroup::model()->findByPk(array('ugid' => $ugid, 'uid' => $uid));
}



/**
* Adds a new user group
*
Expand Down
15 changes: 15 additions & 0 deletions application/models/Permissiontemplates.php
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,21 @@ public function getColumns()
return $cols;
}

/**
* Finds all active records satisfying the specified condition but returns them as array
*
* See {@link find()} for detailed explanation about $condition and $params.
* @param mixed $condition query condition or criteria.
* @param array $params parameters to be bound to an SQL statement.
* @return array list of active records satisfying the specified condition. An empty array is returned if none is found.
*/
public function findAllAsArray($condition = '', $params = [])
{
Yii::trace(get_class($this) . '.findAll()', 'system.db.ar.CActiveRecord');
$criteria = $this->getCommandBuilder()->createCriteria($condition, $params);
return $this->query($criteria, true, false); //Notice the third parameter 'false'
}

/**
* @return SimpleXMLElement
*/
Expand Down
2 changes: 1 addition & 1 deletion application/models/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public function getStatus()
if ($this->load_error == 1) {
return sprintf(
"<span data-bs-toggle='tooltip' title='%s' class='btntooltip ri-close-fill text-danger'></span>",
CHtml::encode(sprintf(gT('Plugin load error : %s'), $this->load_error_message))
CHtml::encode(sprintf(gT('Plugin load error: %s'), $this->load_error_message))
);
} elseif ($this->active == 1) {
return "<span class='ri-checkbox-blank-circle-fill'></span>";
Expand Down
3 changes: 2 additions & 1 deletion application/models/TemplateConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,8 @@ public function getClassAndAttributes()
$aClassAndAttributes['class']['surveylistfooter'] = ' footer ';
$aClassAndAttributes['class']['surveylistfootercont'] = ' ';

$aClassAndAttributes['attr']['surveylistfootercontpaa'] = ' href="http://www.limesurvey.org" target="_blank" ';
$aClassAndAttributes['attr']['surveylistfootercontpaa'] = ' href="https://www.limesurvey.org" target="_blank" ';
$aClassAndAttributes['attr']['surveylistfootercontpab'] = ' href="https://www.limesurvey.org" target="_blank" ';

$aClassAndAttributes['attr']['surveylistrow'] = $aClassAndAttributes['attr']['surveylistrowjumbotron'] = $aClassAndAttributes['attr']['surveylistrowdiva'] = $aClassAndAttributes['attr']['surveylistrowdivadiv'] = $aClassAndAttributes['attr']['surveylistrowdivb'] = $aClassAndAttributes['attr']['surveylistrowdivbdivul'] = '';
$aClassAndAttributes['attr']['surveylistrowdivbdivulli'] = $aClassAndAttributes['attr']['surveylistrowdivc'] = $aClassAndAttributes['attr']['surveylistfooter'] = $aClassAndAttributes['attr']['surveylistfootercont'] = $aClassAndAttributes['class']['surveylistfootercontp'] = '';
Expand Down
19 changes: 19 additions & 0 deletions application/models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -996,6 +996,25 @@ public function isExpired()
return $expired;
}

/**
* Check if user is active
* @return boolean
*/
public function isActive()
{
/* Default is active, user_status must be set (to be tested during DB update); deactivated set user_status to 0 */
return !isset($this->user_status) || $this->user_status !== 0;
}

/**
* Check if user can login
* @return boolean
*/
public function canLogin()
{
return $this->isActive() && !$this->isExpired();
}

/**
* Get the decription to be used in list
* @return $string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@

<!-- modal -->
<div id="file-upload-modal-{{fileid}}" class="modal fade file-upload-modal" role="dialog">
<div class="modal-dialog modal-lg">
<div class="modal-dialog modal-lg modal-dialog-scrollable">

<!-- Modal content-->
<div class="modal-content">
Expand Down