Navigation Menu

Skip to content

Commit

Permalink
Fixed issue #14514: Purpose of permission "update" - CPDB
Browse files Browse the repository at this point in the history
Fixed issue: Administrators now have access to the CPDB if they have shared participants or have global Permissions 'read, create, update, delete', "global Permissions" > "shared Permissions"
  • Loading branch information
ptelu committed May 15, 2019
1 parent dbd5d40 commit 5c9aa86
Show file tree
Hide file tree
Showing 9 changed files with 146 additions and 55 deletions.
81 changes: 59 additions & 22 deletions application/controllers/admin/participantsaction.php
Expand Up @@ -48,8 +48,12 @@ class participantsaction extends Survey_Common_Action

public function runWithParams($params)
{
// $this->checkPermission(['read','create']);
if (!(Permission::model()->hasGlobalPermission('participantpanel', 'read') || Permission::model()->hasGlobalPermission('participantpanel', 'create'))) {
if (!(Permission::model()->hasGlobalPermission('participantpanel', 'read')
|| Permission::model()->hasGlobalPermission('participantpanel', 'create')
|| Permission::model()->hasGlobalPermission('participantpanel', 'update')
|| Permission::model()->hasGlobalPermission('participantpanel', 'delete')
|| ParticipantShare::model()->exists('share_uid = ' . App()->user->id ? App()->user->id : ''))
) {
App()->setFlashMessage(gT('No permission'), 'error');
App()->getController()->redirect(App()->request->urlReferrer);
}
Expand Down Expand Up @@ -303,10 +307,10 @@ public function displayParticipants()
}

// if superadmin all the records in the cpdb will be displayed
$iUserId = App()->user->getId();
if (Permission::model()->hasGlobalPermission('superadmin', 'read')) {
$iTotalRecords = Participant::model()->count();
} else {// if not only the participants on which he has right on (shared and owned)
$iUserId = Yii::app()->user->getId();
$iTotalRecords = Participant::model()->getParticipantsOwnerCount($iUserId);
}
$model = new Participant();
Expand Down Expand Up @@ -345,7 +349,7 @@ public function displayParticipants()
Yii::app()->clientScript->registerPackage('bootstrap-switch');

// check global and custom permissions and pass them to $aData
$permissions = permissionsAsArray(
$aData['permissions'] = permissionsAsArray(
[
'superadmin' => ['read'],
'templates' => ['read'],
Expand All @@ -358,15 +362,16 @@ public function displayParticipants()
[
'participantpanel' => [
'editSharedParticipants' => empty(ParticipantShare::model()->findAllByAttributes(
['share_uid' => App()->user->id ? App()->user->id : ''],
['share_uid' => $iUserId],
['condition' => 'can_edit = \'0\' OR can_edit = \'\'',]
)),
'sharedParticipantExists' => ParticipantShare::model()->exists('share_uid = ' . App()->user->id ? App()->user->id : '')
'sharedParticipantExists' => ParticipantShare::model()->exists('share_uid = ' . $iUserId),
'isOwner' => isset($participantParam['owner_uid']) && ($participantParam['owner_uid'] === $iUserId) ? true : false
],

]
);
$aData['massiveAction'] = App()->getController()->renderPartial('/admin/participants/massive_actions/_selector', array('permissions' => $permissions), true, false);
$aData['massiveAction'] = App()->getController()->renderPartial('/admin/participants/massive_actions/_selector', array('permissions' => $aData['permissions']), true, false);

// Set page size
if ($request->getPost('pageSizeParticipantView')) {
Expand Down Expand Up @@ -585,8 +590,15 @@ public function editParticipant()
}
}

public function batchEdit() {
if (!Permission::model()->hasGlobalPermission('participantpanel', 'update')) {
public function batchEdit()
{
$hasUpdatePermission = Permission::model()->hasGlobalPermission('participantpanel', 'update');
if (!$hasUpdatePermission
&& empty(ParticipantShare::model()->findAllByAttributes(
['share_uid' => App()->user->id ? App()->user->id : ''],
['condition' => 'can_edit = 1',]
))
) {
Yii::app()->user->setFlash('error', gT("Access denied"));
$this->getController()->redirect(Yii::app()->createUrl('/admin'));
return;
Expand Down Expand Up @@ -622,13 +634,22 @@ public function batchEdit() {
$oParticipant->$key = $value;
}

$bUpdateSuccess = $oParticipant->save();
// Check if the User is allowed to edit the participant
if (ParticipantShare::model()->canEditSharedParticipant($sParticipantId)
|| $oParticipant->isOwnerOrSuperAdmin()
|| $hasUpdatePermission
) {
$bUpdateSuccess = $oParticipant->save();
} else {
$bUpdateSuccess = '';
};

if ($bUpdateSuccess) {
$aResults[$sParticipantId]['status'] = true;
$aResults[$sParticipantId]['message'] = gT('Updated');
} else {
$aResults[$sParticipantId]['status'] = false;
$aResults[$sParticipantId]['message'] = $oParticipant->error;
$aResults[$sParticipantId]['message'] = $oParticipant->getError('participant_id');
}
}
} else {
Expand Down Expand Up @@ -2084,15 +2105,18 @@ public function setSession()

/**
* Stores the shared participant information in participant_shares
*
* @return void
* @throws CException
*/
public function shareParticipants()
{
if (!Permission::model()->hasGlobalPermission('participantpanel', 'update')) {
ls\ajax\AjaxHelper::outputNoPermission();
return;
}

$hasUpdatePermission = Permission::model()->hasGlobalPermission('update');
$isSuperAdmin = Permission::model()->hasGlobalPermission('superadmin', 'read');
$permissions = [
'hasUpdatePermission' => $hasUpdatePermission,
'isSuperAdmin' => $isSuperAdmin
];
$participantIds = Yii::app()->request->getPost('participant_id');
$iShareUserId = Yii::app()->request->getPost('shareuser');
$bCanEdit = Yii::app()->request->getPost('can_edit') == 'on';
Expand All @@ -2108,7 +2132,7 @@ public function shareParticipants()

$i = 0;
// $iShareUserId == 0 means any user
if (Permission::model()->hasGlobalPermission('participantpanel', 'update') && $iShareUserId !== '') {
if ($iShareUserId !== '') {
foreach ($participantIds as $id) {
$time = time();
$aData = array(
Expand All @@ -2117,31 +2141,43 @@ public function shareParticipants()
'date_added' => date('Y-m-d H:i:s', $time),
'can_edit' => $bCanEdit
);
ParticipantShare::model()->storeParticipantShare($aData);
ParticipantShare::model()->storeParticipantShare($aData, $permissions);
$i++;
}
}
ls\ajax\AjaxHelper::outputSuccess(sprintf(gT("%s participants have been shared"), $i));
}

/**
* Stores the shared participant information in participant_shares for ONE participant
* Stores the shared participant information in participant_shares for ONE participant *
*
* @return void
* @throws CException
* TODO: Is this function even used anymore? Seems all logic goes through shareParticipants()
*/
public function shareParticipant()
{
$hasUpdatePermission = Permission::model()->hasGlobalPermission('update');
$isSuperAdmin = Permission::model()->hasGlobalPermission('superadmin', 'read');
$permissions = [
'hasUpdatePermission' => $hasUpdatePermission,
'isSuperAdmin' => $isSuperAdmin
];

$iParticipantId = Yii::app()->request->getPost('participant_id');
$bCanEdit = Yii::app()->request->getPost('can_edit');

if (Permission::model()->hasGlobalPermission('participantpanel', 'update')) {
if (ParticipantShare::model()->canEditSharedParticipant($iParticipantId)
|| $hasUpdatePermission
|| $isSuperAdmin) {
$time = time();
$aData = array(
'participant_id' => $iParticipantId,
'share_uid' => yii::app()->user->getId(),
'date_added' => date('Y-m-d H:i:s', $time),
'can_edit' => $bCanEdit
);
ParticipantShare::model()->storeParticipantShare($aData);
ParticipantShare::model()->storeParticipantShare($aData, $permissions);

ls\ajax\AjaxHelper::outputSuccess(gT("Participant shared."));
} else {
Expand Down Expand Up @@ -2239,7 +2275,8 @@ public function changeSharedEditableStatus()
{
$participant_id = Yii::app()->request->getPost('participant_id');
$can_edit = Yii::app()->request->getPost('can_edit');
$shareModel = ParticipantShare::model()->findByAttributes(array('participant_id' => $participant_id));
$share_uid = Yii::app()->request->getPost('share_uid');
$shareModel = ParticipantShare::model()->findByAttributes(array('participant_id' => $participant_id, 'share_uid' => $share_uid));

if ($shareModel) {
$shareModel->can_edit = ($can_edit == 'true' ? 1 : 0);
Expand Down
22 changes: 13 additions & 9 deletions application/models/Participant.php
Expand Up @@ -2101,10 +2101,9 @@ public function userHasPermissionToEdit()
{
$userId = Yii::app()->user->id;

$shared = ParticipantShare::model()->findByAttributes(array(
'participant_id' => $this->participant_id
));

$shared = ParticipantShare::model()->findByAttributes(
['participant_id' => $this->participant_id], 'share_uid = ' . $userId. ' AND can_edit = 1'
);
$owner = $this->owner_uid == $userId;

if (Permission::model()->hasGlobalPermission('superadmin') || (Permission::model()->hasGlobalPermission('participantpanel', 'update'))) {
Expand All @@ -2113,7 +2112,7 @@ public function userHasPermissionToEdit()
} else if ($shared && $shared->share_uid == -1 && $shared->can_edit) {
// -1 = shared with everyone
return true;
} else if ($shared && $shared->share_uid == $userId && $shared->can_edit) {
} else if ($shared && $shared->exists('share_uid' == $userId) && $shared->can_edit) {
// Shared with this particular user
return true;
} else if ($owner) {
Expand Down Expand Up @@ -2188,12 +2187,12 @@ public function permissionCheckedActionsArray($aActions, $permissions)
if (isset($aAction['action'])) {
switch ($aAction['action']) {
case 'delete':
if ($permissions['superadmin']['read'] || $permissions['participantpanel']['delete'] || !$permissions['participantpanel']['sharedParticipantExists']) {
if ($permissions['participantpanel']['isOwner'] || $permissions['superadmin']['read'] || $permissions['participantpanel']['delete'] || !$permissions['participantpanel']['sharedParticipantExists']) {
array_push($checkedActions, $aAction);
}
break;
case 'batchEdit':
if ($permissions['superadmin']['read']
if ($permissions['participantpanel']['isOwner'] || $permissions['superadmin']['read']
|| $permissions['participantpanel']['update']
|| $permissions['participantpanel']['editSharedParticipants']
|| !$permissions['participantpanel']['sharedParticipantExists']
Expand All @@ -2202,12 +2201,17 @@ public function permissionCheckedActionsArray($aActions, $permissions)
}
break;
case 'export':
if ($permissions['superadmin']['read'] || $permissions['participantpanel']['export'] || !$permissions['participantpanel']['sharedParticipantExists']) {
if ($permissions['participantpanel']['isOwner'] || $permissions['superadmin']['read'] || $permissions['participantpanel']['export'] || !$permissions['participantpanel']['sharedParticipantExists']) {
array_push($checkedActions, $aAction);
}
break;
case 'share':
if ($permissions['superadmin']['read'] || $permissions['participantpanel']['update'] || !$permissions['participantpanel']['sharedParticipantExists']) {
if ($permissions['participantpanel']['isOwner']
|| $permissions['superadmin']['read']
|| $permissions['participantpanel']['update']
|| !$permissions['participantpanel']['sharedParticipantExists']
|| $permissions['participantpanel']['editSharedParticipants']
) {
array_push($checkedActions, $aAction);
}
break;
Expand Down
41 changes: 37 additions & 4 deletions application/models/ParticipantShare.php
Expand Up @@ -11,6 +11,9 @@
* See COPYRIGHT.php for copyright notices and details.
*
*/

use ls\ajax\AjaxHelper;

/**
* This is the model class for table "{{participant_shares}}".
*
Expand Down Expand Up @@ -229,6 +232,7 @@ public function getColumns()
array(
"name" => 'share_uid',
"value" => '$data->sharedBy',
"type" => 'raw',
"header" => gT("Shared by"),
"filter" => $this->getSharedByList($this->share_uid)
),
Expand Down Expand Up @@ -317,14 +321,25 @@ public function search()

/**
* @param array $data
* @param array $permission
*
* @return void
* @throws CException
*/
public function storeParticipantShare($data)
public function storeParticipantShare($data, $permission)
{
$ownerid = Yii::app()->db->createCommand()->select('*')->from('{{participants}}')->where('participant_id = :participant_id')->bindParam(":participant_id", $data['participant_id'], PDO::PARAM_STR)->queryRow();
$hasUpdatePermission = isset($permission['hasUpdatePermission'])? $permission['hasUpdatePermission'] : false;
$isSuperAdmin = isset($permission['isSuperAdmin'])? $permission['isSuperAdmin'] : false;
$userId = App()->user->getId();
$ownerid = App()->db->createCommand()->select('*')->from('{{participants}}')->where('participant_id = :participant_id')->bindParam(":participant_id", $data['participant_id'], PDO::PARAM_STR)->queryRow();

// CHeck if share already exists
$arShare = $this->findByPk(array('participant_id'=>$data['participant_id'], 'share_uid'=>$data['share_uid']));
if ($ownerid['owner_uid'] == $data['share_uid']) {
$arShare = $this->findByPk(['participant_id' => $data['participant_id'], 'share_uid' => $data['share_uid']]);
$canEditShared = $this->canEditSharedParticipant($data['participant_id']);
$isOwner = $ownerid['owner_uid'] == $userId;

if ($ownerid['owner_uid'] == $data['share_uid'] || (!$permission && !$canEditShared && !$isOwner && !$isSuperAdmin && !$hasUpdatePermission)) {
ls\ajax\AjaxHelper::outputNoPermission();
return;
}
if (is_null($arShare)) {
Expand Down Expand Up @@ -376,4 +391,22 @@ public function getOwnerName()
return $this->participant->owner->full_name;
}

/**
* Returns true if the user is allowed to edit the participant
*
* @param $participent_id
*
* @return boolean
*/
public function canEditSharedParticipant($participent_id)
{
$participent = $this->findByAttributes(
['participant_id' => $participent_id],
['condition' => 'can_edit = 1 AND share_uid = ' . App()->user->getId()]);
if ($participent) {
return true;
}
return false;
}

}
Expand Up @@ -12,11 +12,15 @@
<?php eT("Central participant management"); ?>
</div>
<div class="col-xs-4 text-right">
<button class="btn btn-default" id="addParticipantToCPP">
<i class="fa fa-plus-circle text-success"></i>
&nbsp;
<?php eT("Add new participant"); ?>
</button>
<?php if (
Permission::model()->hasGlobalPermission('superadmin', 'read')
|| Permission::model()->hasGlobalPermission('participantpanel', 'create')
): ?>
<button class="btn btn-default" id="addParticipantToCPP">
<i class="fa fa-plus-circle text-success"></i>&nbsp;
<?php eT("Add new participant"); ?>
</button>
<?php endif; ?>
</div>
</div>
<div class="row" style="margin-bottom: 100px">
Expand Down
Expand Up @@ -59,7 +59,8 @@
<span class="fa fa-list text-success"></span>
<?php eT("Display CPDB participants");?>
</a>
<?php elseif (Permission::model()->hasGlobalPermission('participantpanel','create')):?>
<?php elseif (Permission::model()->hasGlobalPermission('participantpanel','create')
|| ParticipantShare::model()->exists('share_uid = ' . App()->user->getId())):?>
<!-- Display my participants -->
<a class="btn btn-default pjax" href="<?php echo $this->createUrl("admin/participants/sa/displayParticipants"); ?>" role="button">
<span class="fa fa-list text-success"></span>
Expand Down
2 changes: 1 addition & 1 deletion application/views/admin/participants/sharePanel_view.php
Expand Up @@ -18,7 +18,7 @@
'itemsCssClass' => 'table table-striped items',
'htmlOptions' => array('class'=> 'table-responsive'),
'dataProvider' => $model->search(),
'rowHtmlOptionsExpression' => '["data-participant_id" => $data->participant_id ]',
'rowHtmlOptionsExpression' => '["data-participant_id" => $data->participant_id, "data-share_uid" => $data->share_uid]',
'columns' => $model->columns,
'filter'=>$model,
'ajaxType' => 'POST',
Expand Down

0 comments on commit 5c9aa86

Please sign in to comment.