HEX
Server: Apache
System: Linux WWW 6.1.0-40-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.153-1 (2025-09-20) x86_64
User: web11 (1011)
PHP: 8.2.29
Disabled: NONE
Upload Files
File: /var/www/apklausos/application/models/services/SurveyPermissions.php
<?php

namespace LimeSurvey\Models\Services;

use CActiveDataProvider;
use CSort;
use Yii;

/**
 * This class is responsible for the relationship between permissions, users and surveys.
 * It could be handled as a specific permissions system for surveys.
 *
 */
class SurveyPermissions
{
    /** @var \Survey */
    private $survey;

    /** @var bool */
    private $userControlSameGroupPolicy;

    /**
     * SurveyPermissions constructor.
     *
     * @param \Survey $survey
     * @param bool $userControlSameGroupPolicy
     */
    public function __construct(\Survey $survey, $userControlSameGroupPolicy)
    {
        $this->survey = $survey;
        $this->userControlSameGroupPolicy = $userControlSameGroupPolicy;
    }

    /**
     * Returns an array with data about users and their specific permissions
     * for the survey. The returned array could be empty if there are no users
     * with permissions for this survey.
     *
     * @return \Permission[]
     */
    public function getUsersSurveyPermissions()
    {
        $userPermissionCriteria = $this->getUserPermissionCriteria();
        return \Permission::model()->findAll($userPermissionCriteria);
    }

    /**
     * @return CActiveDataProvider
     */
    public function getUsersSurveyPermissionsDataProvider(): CActiveDataProvider
    {
        $pageSize = App()->user->getState('pageSize', App()->params['defaultPageSize']);
        $userPermissionCriteria = $this->getUserPermissionCriteria();
        // $sort = new CSort();
        // $sort->attributes = array(
        //     'users_name' => array(
        //         'asc' => 'users_name asc',
        //         'desc' => 'users_name desc',
        //     ),
        //     'full_name' => array(
        //         'asc'  => 'u.full_name asc',
        //         'desc' => 'u.full_name desc',
        //     ),

        // );
        // $sort->defaultOrder = array('creation_date' => CSort::SORT_DESC);

        $dataProvider = new CActiveDataProvider('Permission', [
            // 'sort' => $sort,
            'criteria' => $userPermissionCriteria,
            'pagination' => array(
                'pageSize' => $pageSize,
            ),
        ]);
        return $dataProvider;
    }

    /**
     * Returns a CDbCriteria object which selects columns from table
     * permissions and users taking care of samegrouppolicy and not logged in
     * user for this survey.
     *
     * @return \CDbCriteria
     */
    public function getUserPermissionCriteria()
    {
        $userList = getUserList('onlyuidarray'); // Limit the user list for the samegrouppolicy
        /** @var \LSYii_Application */
        $app = \Yii::app();
        $currentUserId = $app->user->getId(); //current logged in user
        $criteria = new \CDbCriteria();
        $criteria->select = 't.entity_id, t.uid, u.users_name AS username, u.full_name';
        $criteria->join = 'INNER JOIN {{users}} AS u ON t.uid = u.uid';
        $criteria->condition = 't.entity_id =:entity_id';
        $criteria->addCondition('t.entity =:entity');
        $criteria->addNotInCondition('u.uid', [$currentUserId]);
        $criteria->addInCondition('t.uid', $userList);
        $criteria->params = array_merge($criteria->params, [
            ':entity_id' => $this->survey->sid,
            ':entity'    => 'survey'
        ]);
        $criteria->group = 't.entity_id, t.uid, u.users_name, u.full_name';
        $criteria->order = 'u.users_name';

        return $criteria;
    }

    /**
     * Get the permissions (crud + import,export) for a survey permission like 'assessements'
     *
     * @param int $userid the userid
     * @param string $permission the survey permission (e.g. 'assessments', 'responses')
     * @return \Permission|null
     */
    public function getUsersSurveyPermissionEntity($userid, $permission)
    {
        $criteria = new \CDbCriteria();
        $criteria->select = 'create_p, read_p, update_p, delete_p, import_p, export_p';
        $criteria->condition = 'entity_id =:entity_id';
        $criteria->addCondition('entity =:entity');
        $criteria->addCondition('permission =:permission');
        $criteria->addCondition('uid=:userid');
        $criteria->params = [
                ':entity_id' => $this->survey->sid,
                ':entity'    => 'survey',
                ':permission' => $permission,
                ':userid' => $userid
        ];
        return \Permission::model()->findByAttributes([
            'entity_id' => $this->survey->sid,
            'entity' => 'survey',
            'permission' => $permission,
            'uid' => $userid
        ]);
    }

    /**
     * Adds a user to the survey permissions. This includes that the user gets the
     * permission 'read' for this survey.
     *
     * @param int $userid the userid
     * @return boolean true if user could be added, false otherwise
     */
    public function addUserToSurveyPermission($userid)
    {
        $isResult = false;
        $user = \User::model()->findByPk($userid);
        if (isset($user) && in_array($userid, getUserList('onlyuidarray'))) {
            $isResult = \Permission::model()->insertSomeRecords(
                array(
                'entity_id' => $this->survey->sid,
                'entity' => 'survey',
                'uid' => $userid,
                'permission' => 'survey',
                'read_p' => 1)
            );
        }

        return $isResult;
    }

    /**
     * Adds users from a group to survey permissions.
     * This includes that the users get the
     * permission 'read' for this survey.
     *
     * @param int $userGroupId the user group id
     * @return int amount of users from the given group added
     */
    public function addUserGroupToSurveyPermissions($userGroupId)
    {
        $amountAdded = 0;
        $userGroup = \UserGroup::model()->findByPk($userGroupId);
        if (
            isset($userGroup) && in_array(
                $userGroupId,
                array_column($this->getSurveyUserGroupList(), 'ugid')
            )
        ) {
            $users = \User::model()->getCommonUID($this->survey->sid, $userGroupId); //Checked
            $users = $users->readAll();
            if (count($users) > 0) {
                foreach ($users as $user) {
                    $isResult = \Permission::model()->insertSomeRecords(
                        [
                            'entity_id' => $this->survey->sid,
                            'entity' => 'survey',
                            'uid' => $user['uid'],
                            'permission' => 'survey',
                            'read_p' => 1
                        ]
                    );
                    if ($isResult) {
                        $amountAdded++;
                    }
                }
            }
        }
        return $amountAdded;
    }

    /**
     * Returns a list of users which still not have survey permissions and
     * could be added to survey permissions,
     * including the check for usercontrolSameGroupPolicy (see config file for more information).
     *
     * @return array
     */
    public function getSurveyUserList()
    {
        $aUserIds = $this->getUserIdsWithSurveyPermissions();
        $criteria = new \CDbCriteria();
        $criteria->select = 't.uid, t.users_name, t.full_name';
        $criteria->addNotInCondition('t.uid', $aUserIds);
        $users = \User::model()->findAll($criteria);

        $authorizedUsersList = [];
        $userList = [];

        if ($this->userControlSameGroupPolicy) {
            $authorizedUsersList = getUserList('onlyuidarray');
        }
        $index = 0;
        foreach ($users as $user) {
            if (
                !$this->userControlSameGroupPolicy || in_array($user->uid, $authorizedUsersList)
            ) {
                $userList[$index]['userid'] = $user->uid;
                $userList[$index]['fullname'] = $user->full_name;
                $userList[$index]['usersname'] = $user->users_name;
                $index++;
            }
        }
        return $userList;
    }


    /**
     * Return a list (array) of user groups which could still be added to survey permissions.
     * A user group could be added to survey permissions if there is at least one user in the group
     * which has not already been added to survey permissions of this survey.
     *
     * @return array containing ['ugid'] and ['name']
     */
    public function getSurveyUserGroupList()
    {
        //find all groups that have not all their users already in 'survey permissions'
        $criteria = new \CDbCriteria();
        $criteria->select = "t.ugid, t.name, MAX(d.ugid)";
        $criteria->join = "LEFT JOIN (
        SELECT b.ugid
        FROM {{user_in_groups}} AS b
            LEFT JOIN (
                SELECT * FROM {{permissions}}
                WHERE entity_id =:surveyid and entity='survey'
            ) AS c ON b.uid = c.uid WHERE c.uid IS NULL
        ) AS d ON t.ugid = d.ugid";
        $criteria->params = [
            'surveyid' => $this->survey->sid,
        ];
        $criteria->group = 't.ugid, t.name';
        $criteria->having = 'MAX(d.ugid) IS NOT NULL'; //make sure that there is at least one possible group
        $criteria->order = 't.name';

        $userGroups = \UserGroup::model()->findAll($criteria);

        $authorizedGroupsList = getUserGroupList();
        $simpleugidarray = [];
        $index = 0;
        foreach ($userGroups as $userGroup) {
            if (in_array($userGroup->ugid, $authorizedGroupsList)) {
                $simpleugidarray[$index]['ugid'] = $userGroup->ugid;
                $simpleugidarray[$index]['name'] = $userGroup->name;
                $index++;
            }
        }
        return $simpleugidarray;
    }

    /**
     * Saves (inserts ) the survey permissions for a specific user.
     *
     * @param int $userId
     * @param array $permissions
     * @return bool true if all permissions could be saved, false otherwise
     */
    public function saveUserPermissions($userId, $permissions)
    {
        $isSaved = true;

        //delete current survey permissions and reset the new ones
        // ...easier as to compare all of them
        $this->deleteUserPermissions($userId);

        //but user has always 'read' permission for this specific survey ...
        $permissions['survey']['read'] = 1;

        foreach ($permissions as $permission => $key) {
            $isSaved = $isSaved && \Permission::model()->insertSomeRecords(
                [
                    'entity_id' => $this->survey->sid,
                    'entity' => 'survey',
                    'uid' => $userId,
                    'permission' => $permission,
                    'create_p' => $key['create'] ?? 0,
                    'read_p' => $key['read'] ?? 0,
                    'update_p' => $key['update'] ?? 0,
                    'delete_p' => $key['delete'] ?? 0,
                    'import_p' => $key['import'] ?? 0,
                    'export_p' => $key['export'] ?? 0,
                ]
            );
        }

        return $isSaved;
    }

    /**
     * Saves (inserts) permissions for a user group.
     *
     * @param int $userGroupId
     * @param array $permissions
     * @return bool
     * @throws \Exception
     */
    public function saveUserGroupPermissions($userGroupId, $permissions)
    {
        $permissionUserID = \Permission::model()->getUserId();
        $surveysGroups    = \SurveysGroups::model()->findByPk($this->survey->sid);
        if ($surveysGroups !== null) {
            $surveysGroupsOwnerID = $surveysGroups->getOwnerId();
            /** @var \UserInGroup[] */
            $oUserInGroups = \UserInGroup::model()->findAll(
                'ugid = :ugid AND uid <> :currentUserId AND uid <> :surveygroupsOwnerId',
                array(
                    ':ugid' => $userGroupId,
                    ':currentUserId' => $permissionUserID, // Don't need to set to current user
                    ':surveygroupsOwnerId' => $surveysGroupsOwnerID, // Don't need to set to owner (?) , get from surveyspermission
                )
            );
        } else {
            /** @var \UserInGroup[] */
            $oUserInGroups = \UserInGroup::model()->findAll(
                'ugid = :ugid AND uid <> :currentUserId',
                array (
                    ':ugid' => $userGroupId,
                    ':currentUserId' => $permissionUserID
                )
            );
        }
        $success = true;
        foreach ($oUserInGroups as $userInGroup) {
            /* @var $userInGroup \UserInGroup */
            $success = $success && $this->saveUserPermissions($userInGroup->uid, $permissions);
        }
        return $success;
    }

    /** Deletes all permissions for a user for this survey.
     *
     * @param int $userId
     * @return int number of deleted permissions, 0 means nothing has been deleted
     */
    public function deleteUserPermissions($userId)
    {
        return \Permission::model()->deleteAllByAttributes([
            'entity_id' => $this->survey->sid,
            'entity' => 'survey',
            'uid' => $userId
        ]);
    }

    /**
     * Returns an array of user group names including 'usercontrolSameGroupPolicy' if set.
     *
     * @param int $userid
     * @param bool $usercontrolSameGroupPolicy
     * @return array names of user groups, or empty array
     */
    public function getUserGroupNames($userid, $usercontrolSameGroupPolicy)
    {
        $group_names = [];
        $authorizedGroupsList = getUserGroupList();
        /** @var \UserInGroup[] */
        $userInGroups = \UserInGroup::model()->with('users')->findAll('users.uid = :uid', array(':uid' => $userid));
        foreach ($userInGroups as $userGroup) {
            /* @var $userGroup \UserInGroup */
            if (!$usercontrolSameGroupPolicy || in_array($userGroup->ugid, $authorizedGroupsList)) {
                $group_names[] = $userGroup->group->name;
            }
        }

        return $group_names;
    }

    /**
     * Checks which permission entities (CRUD + import,export) a user has for the specific
     * permission (e.g. permissionName='assessment'). Returns an array with infos.
     *
     * @param int $userId    the user id
     * @param string $permissioName     permission name (e.g. 'assessments' or 'quotas')
     * @param array $basicPermissionDetails array with basic information about a permission
     *                         (e.g. permission name, single permissions(CRUD) etc.)
     * @return array  structure is ['hasPermissions'] --> if user has at least one permission entity
     *                             ['allPermissions'] --> does the user has ALL possible permission entities
     *                             ['permissionCrudArray'] --> array with permission entities the user has
     */
    public function getTooltipAllPermissions($userId, $permissioName, $basicPermissionDetails)
    {
        $iCount = 0;
        $iPermissionCount = 0;
        $permissionCrudArray = [];
        foreach ($basicPermissionDetails as $sPDetailKey => $sPDetailValue) {
            $userHasPermission = \Permission::model()->hasSurveyPermission($this->survey->sid, $permissioName, $sPDetailKey, $userId);
            if ($sPDetailValue && $userHasPermission) {
                $iCount++;
                $permissionCrudArray[] = $sPDetailKey;
            }
            if (in_array($sPDetailKey, \PermissionInterface::SINGLE_PERMISSIONS) && $sPDetailValue) {
                $iPermissionCount++;
            }
        }
        return [
            'hasPermissions' => $iCount > 0,
            'allPermissionsSet' => $iCount == $iPermissionCount,
            'permissionCrudArray' => $permissionCrudArray
        ];
    }

    /**
     * Get the userids which already have survey permissions.
     *
     * @return array
     */
    public function getUserIdsWithSurveyPermissions(): array
    {
        $allUsersWithPermissions = new \CDbCriteria();
        $allUsersWithPermissions->select = 't.uid';
        $allUsersWithPermissions->condition = 't.entity_id=:entityId';
        $allUsersWithPermissions->addCondition('t.entity=:entity');
        $allUsersWithPermissions->params = [
            'entityId' => $this->survey->sid,
            'entity' => 'survey'
        ];
        $allUsersWithPermissions->group = 't.uid';
        $resultUserIds = \Permission::model()->findAll($allUsersWithPermissions);
        $aUserIds = [];
        foreach ($resultUserIds as $userid) {
            $aUserIds[] = $userid->uid;
        }
        return $aUserIds;
    }
}