Skip to content
Snippets Groups Projects
UserController.php 77.2 KiB
Newer Older
  • Learn to ignore specific revisions
  • <?php
    
    /**
    * Copyright Maarch since 2008 under licence GPLv3.
    * See LICENCE.txt file at the root folder for more details.
    * This file is part of Maarch software.
    *
    */
    
    /**
    * @brief User Controller
    * @author dev@maarch.org
    */
    
    
    namespace User\controllers;
    
    Damien's avatar
    Damien committed
    use Basket\models\BasketModel;
    
    use Basket\models\GroupBasketModel;
    
    Damien's avatar
    Damien committed
    use Basket\models\RedirectBasketModel;
    
    use ContentManagement\controllers\DocumentEditorController;
    
    use Docserver\controllers\DocserverController;
    
    use Docserver\models\DocserverModel;
    
    use Email\controllers\EmailController;
    
    Damien's avatar
    Damien committed
    use Entity\models\EntityModel;
    
    use Entity\models\ListInstanceModel;
    
    use Entity\models\ListTemplateItemModel;
    
    Damien's avatar
    Damien committed
    use Entity\models\ListTemplateModel;
    
    use Firebase\JWT\JWT;
    use Group\controllers\PrivilegeController;
    
    use Group\models\GroupModel;
    
    Damien's avatar
    Damien committed
    use History\controllers\HistoryController;
    use History\models\HistoryModel;
    
    Nathan Cheval's avatar
    Nathan Cheval committed
    use Notification\controllers\NotificationsEventsController;
    use Parameter\models\ParameterModel;
    
    Damien's avatar
    Damien committed
    use Resource\controllers\ResController;
    
    use Resource\controllers\StoreController;
    
    use Resource\models\ResModel;
    
    use Resource\models\UserFollowedResourceModel;
    
    Alex ORLUC's avatar
    Alex ORLUC committed
    use Respect\Validation\Validator;
    
    use Slim\Http\Request;
    use Slim\Http\Response;
    
    use SrcCore\controllers\AuthenticationController;
    
    Damien's avatar
    Damien committed
    use SrcCore\controllers\PasswordController;
    
    use SrcCore\controllers\UrlController;
    
    Damien's avatar
    Damien committed
    use SrcCore\models\AuthenticationModel;
    
    Damien's avatar
    Damien committed
    use SrcCore\models\CoreConfigModel;
    
    Damien's avatar
    Damien committed
    use SrcCore\models\DatabaseModel;
    
    use SrcCore\models\PasswordModel;
    
    use Template\models\TemplateModel;
    
    use User\models\UserBasketPreferenceModel;
    
    use User\models\UserEntityModel;
    
    use User\models\UserGroupModel;
    
    Damien's avatar
    Damien committed
    use User\models\UserModel;
    
    use User\models\UserSignatureModel;
    
        const ALTERNATIVES_CONNECTIONS_METHODS = ['sso', 'cas', 'ldap', 'ozwillo', 'shibboleth'];
    
    Damien's avatar
    Damien committed
        public function get(Request $request, Response $response)
        {
    
            if (!PrivilegeController::hasPrivilege(['privilegeId' => 'admin_users', 'userId' => $GLOBALS['id']])) {
    
    Damien's avatar
    Damien committed
                return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
            }
    
            if ($GLOBALS['userId'] == 'superadmin') {
                $users = UserModel::get([
    
                    'select'    => ['id', 'user_id', 'firstname', 'lastname', 'status', 'mail'],
    
    Damien's avatar
    Damien committed
                    'where'     => ['user_id != ?', 'status != ?'],
                    'data'      => ['superadmin', 'DEL']
                ]);
            } else {
                $entities = EntityModel::getAllEntitiesByUserId(['userId' => $GLOBALS['userId']]);
    
                $users = [];
                if (!empty($entities)) {
    
                    $users = UserEntityModel::getWithUsers([
    
                        'select'    => ['DISTINCT users.id', 'users.user_id', 'firstname', 'lastname', 'status', 'mail'],
    
                        'where'     => ['users_entities.entity_id in (?)', 'status != ?'],
                        'data'      => [$entities, 'DEL']
    
                $usersNoEntities = UserEntityModel::getUsersWithoutEntities(['select' => ['id', 'users.user_id', 'firstname', 'lastname', 'status', 'mail']]);
    
                $users = array_merge($users, $usersNoEntities);
    
    Damien's avatar
    Damien committed
            }
    
            $usersIds = [];
            foreach ($users as $value) {
                $usersIds[] = $value['user_id'];
            }
    
    
    Nathan Cheval's avatar
    Nathan Cheval committed
            $quota = [];
            $userQuota = ParameterModel::getById(['id' => 'user_quota', 'select' => ['param_value_int']]);
            if (!empty($userQuota['param_value_int'])) {
    
                $activeUser = UserModel::get(['select' => ['count(1)'], 'where' => ['status = ?', 'user_id <> ?'], 'data' => ['OK','superadmin']]);
                $inactiveUser = UserModel::get(['select' => ['count(1)'], 'where' => ['status = ?', 'user_id <> ?'], 'data' => ['SPD','superadmin']]);
    
    Nathan Cheval's avatar
    Nathan Cheval committed
                $quota = ['actives' => $activeUser[0]['count'], 'inactives' => $inactiveUser[0]['count'], 'userQuota' => $userQuota['param_value_int']];
            }
    
            return $response->withJson(['users' => $users, 'quota' => $quota]);
    
        public function getById(Request $request, Response $response, array $args)
        {
            $user = UserModel::getById(['id' => $args['id'], 'select' => ['id', 'firstname', 'lastname']]);
            if (empty($user)) {
                return $response->withStatus(400)->withJson(['errors' => 'User does not exist']);
            }
    
            return $response->withJson($user);
        }
    
    
    Damien's avatar
    Damien committed
        public function getDetailledById(Request $request, Response $response, array $aArgs)
        {
            $error = $this->hasUsersRights(['id' => $aArgs['id']]);
            if (!empty($error['error'])) {
                return $response->withStatus($error['status'])->withJson(['errors' => $error['error']]);
            }
    
    
            $user = UserModel::getById(['id' => $aArgs['id'], 'select' => ['id', 'user_id', 'firstname', 'lastname', 'status', 'phone', 'mail', 'initials', 'loginmode', 'external_id']]);
    
            $user['external_id']        = json_decode($user['external_id'], true);
    
    
            if (PrivilegeController::hasPrivilege(['privilegeId' => 'view_personal_data', 'userId' => $GLOBALS['id']])) {
                $user['signatures'] = UserSignatureModel::getByUserSerialId(['userSerialid' => $aArgs['id']]);
                $user['emailSignatures'] = UserModel::getEmailSignaturesById(['userId' => $user['user_id']]);
            } else {
                $user['signatures'] = [];
                $user['emailSignatures'] = [];
                unset($user['phone']);
            }
    
    
            $user['groups']             = UserModel::getGroupsByLogin(['login' => $user['user_id']]);
    
            $user['allGroups']          = GroupModel::getAvailableGroupsByUserId(['userId' => $user['id']]);
    
            $user['entities']           = UserModel::getEntitiesByLogin(['login' => $user['user_id']]);
    
            $user['allEntities']        = EntityModel::getAvailableEntitiesForAdministratorByUserId(['userId' => $user['user_id'], 'administratorUserId' => $GLOBALS['userId']]);
    
            $user['baskets']            = BasketModel::getBasketsByLogin(['login' => $user['user_id']]);
    
            $user['assignedBaskets']    = RedirectBasketModel::getAssignedBasketsByUserId(['userId' => $user['id']]);
            $user['redirectedBaskets']  = RedirectBasketModel::getRedirectedBasketsByUserId(['userId' => $user['id']]);
            $user['history']            = HistoryModel::getByUserId(['userId' => $user['user_id'], 'select' => ['event_type', 'event_date', 'info', 'remote_ip']]);
    
            $user['canModifyPassword']              = false;
            $user['canSendActivationNotification']  = false;
            $user['canCreateMaarchParapheurUser']   = false;
    
            if ($user['loginmode'] == 'restMode') {
                $user['canModifyPassword'] = true;
    
            $loggingMethod = CoreConfigModel::getLoggingMethod();
            if ($user['loginmode'] != 'restMode' && $loggingMethod['id'] == 'standard') {
                $user['canSendActivationNotification'] = true;
            }
    
    
            $loadedXml = CoreConfigModel::getXmlLoaded(['path' => 'modules/visa/xml/remoteSignatoryBooks.xml']);
    
            if ((string)$loadedXml->signatoryBookEnabled == 'maarchParapheur' && $user['loginmode'] != 'restMode' && empty($user['external_id']['maarchParapheur'])) {
    
                $user['canCreateMaarchParapheurUser'] = true;
            }
    
    Damien's avatar
    Damien committed
    
            return $response->withJson($user);
        }
    
    
        public function create(Request $request, Response $response)
    
            if (!PrivilegeController::hasPrivilege(['privilegeId' => 'admin_users', 'userId' => $GLOBALS['id']])) {
    
                return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
            }
    
            $data = $request->getParams();
    
    
            $check = Validator::stringType()->notEmpty()->validate($data['userId']) && preg_match("/^[\w.@-]*$/", $data['userId']);
            $check = $check && Validator::stringType()->notEmpty()->validate($data['firstname']);
            $check = $check && Validator::stringType()->notEmpty()->validate($data['lastname']);
    
    Damien's avatar
    Damien committed
            $check = $check && (empty($data['mail']) || filter_var($data['mail'], FILTER_VALIDATE_EMAIL));
    
            if (PrivilegeController::hasPrivilege(['privilegeId' => 'manage_personal_data', 'userId' => $GLOBALS['id']])) {
                $check = $check && (empty($data['phone']) || preg_match("/\+?((|\ |\.|\(|\)|\-)?(\d)*)*\d$/", $data['phone']));
            }
    
    Damien's avatar
    Damien committed
            if (!$check) {
    
                return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
            }
    
    
            $loggingMethod = CoreConfigModel::getLoggingMethod();
            $existingUser = UserModel::getByLowerLogin(['login' => $data['userId'], 'select' => ['id', 'status', 'mail']]);
    
            if (!empty($existingUser) && $existingUser['status'] == 'DEL') {
    
    Damien's avatar
    Damien committed
                UserModel::update([
                    'set'   => [
    
                        'status'    => 'OK',
                        'password'  => AuthenticationModel::getPasswordHash(AuthenticationModel::generatePassword()),
    
    Damien's avatar
    Damien committed
                    ],
                    'where' => ['id = ?'],
                    'data'  => [$existingUser['id']]
                ]);
    
                if ($loggingMethod['id'] == 'standard') {
    
                    AuthenticationController::sendAccountActivationNotification(['userId' => $existingUser['id'], 'userEmail' => $existingUser['mail']]);
    
                }
    
                return $response->withJson(['id' => $existingUser['id']]);
    
            } elseif (!empty($existingUser)) {
                return $response->withStatus(400)->withJson(['errors' => _USER_ID_ALREADY_EXISTS]);
    
            if (!PrivilegeController::hasPrivilege(['privilegeId' => 'manage_personal_data', 'userId' => $GLOBALS['id']])) {
                $data['phone'] = null;
            }
    
    
    Damien's avatar
    Damien committed
            $logingModes = ['standard', 'restMode'];
            if (!in_array($data['loginmode'], $logingModes)) {
                $data['loginmode'] = 'standard';
            }
    
    
            $preferences = ['documentEdition' => 'java'];
            $allowedMethods = DocumentEditorController::getAllowedMethods();
            if (in_array('onlyoffice', $allowedMethods)) {
                $preferences = ['documentEdition' => 'onlyoffice'];
            }
            $data['preferences'] = json_encode($preferences);
    
    
            $id = UserModel::create(['user' => $data]);
    
    Damien's avatar
    Damien committed
    
    
    Nathan Cheval's avatar
    Nathan Cheval committed
            $userQuota = ParameterModel::getById(['id' => 'user_quota', 'select' => ['param_value_int']]);
            if (!empty($userQuota['param_value_int'])) {
    
                $activeUser = UserModel::get(['select' => ['count(1)'], 'where' => ['status = ?', 'user_id <> ?'], 'data' => ['OK', 'superadmin']]);
    
    Nathan Cheval's avatar
    Nathan Cheval committed
                if ($activeUser[0]['count'] > $userQuota['param_value_int']) {
    
                    NotificationsEventsController::fillEventStack(['eventId' => 'user_quota', 'tableName' => 'users', 'recordId' => 'quota_exceed', 'userId' => 'superadmin', 'info' => _QUOTA_EXCEEDED]);
    
            if ($loggingMethod['id'] == 'standard') {
    
                AuthenticationController::sendAccountActivationNotification(['userId' => $id, 'userEmail' => $data['mail']]);
    
            HistoryController::add([
                'tableName'    => 'users',
                'recordId'     => $GLOBALS['userId'],
                'eventType'    => 'ADD',
                'eventId'      => 'userCreation',
                'info'         => _USER_CREATED . " {$data['userId']}"
            ]);
    
    
            return $response->withJson(['id' => $id]);
    
        public function update(Request $request, Response $response, array $aArgs)
    
    Damien's avatar
    Damien committed
            $error = $this->hasUsersRights(['id' => $aArgs['id']]);
    
            if (!empty($error['error'])) {
                return $response->withStatus($error['status'])->withJson(['errors' => $error['error']]);
    
            $data = $request->getParams();
    
    
    Damien's avatar
    Damien committed
            $check = Validator::stringType()->notEmpty()->validate($data['firstname']);
    
            $check = $check && Validator::stringType()->notEmpty()->validate($data['lastname']);
    
    Damien's avatar
    Damien committed
            $check = $check && (empty($data['mail']) || filter_var($data['mail'], FILTER_VALIDATE_EMAIL));
    
            if (PrivilegeController::hasPrivilege(['privilegeId' => 'manage_personal_data', 'userId' => $GLOBALS['id']])) {
                $check = $check && (empty($data['phone']) || preg_match("/\+?((|\ |\.|\(|\)|\-)?(\d)*)*\d$/", $data['phone']));
            }
    
    Damien's avatar
    Damien committed
            if (!$check) {
    
                return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
            }
    
    
    Damien's avatar
    Damien committed
            $set = [
                'firstname' => $data['firstname'],
                'lastname'  => $data['lastname'],
                'mail'      => $data['mail'],
                'initials'  => $data['initials'],
                'loginmode' => empty($data['loginmode']) ? 'standard' : $data['loginmode'],
            ];
    
    
            if (PrivilegeController::hasPrivilege(['privilegeId' => 'manage_personal_data', 'userId' => $GLOBALS['id']])) {
                $set['phone'] = $data['phone'];
            }
    
    
            if (!empty($data['status']) && $data['status'] == 'OK') {
                $set['status'] = 'OK';
    
    Damien's avatar
    Damien committed
            }
    
            $userQuota = ParameterModel::getById(['id' => 'user_quota', 'select' => ['param_value_int']]);
            $user = [];
            if (!empty($userQuota['param_value_int'])) {
                $user = UserModel::getById(['id' => $aArgs['id'], 'select' => ['status']]);
            }
    
    
    Damien's avatar
    Damien committed
            UserModel::update([
                'set'   => $set,
                'where' => ['id = ?'],
                'data'  => [$aArgs['id']]
            ]);
    
    Damien's avatar
    Damien committed
            if (!empty($userQuota['param_value_int'])) {
    
                if ($user['status'] == 'SPD' && $data['status'] == 'OK') {
                    $activeUser = UserModel::get(['select' => ['count(1)'], 'where' => ['status = ?', 'user_id != ?'], 'data' => ['OK', 'superadmin']]);
    
    Damien's avatar
    Damien committed
                    if ($activeUser[0]['count'] > $userQuota['param_value_int']) {
                        NotificationsEventsController::fillEventStack(['eventId' => 'user_quota', 'tableName' => 'users', 'recordId' => 'quota_exceed', 'userId' => 'superadmin', 'info' => _QUOTA_EXCEEDED]);
                    }
    
            HistoryController::add([
                'tableName'    => 'users',
                'recordId'     => $GLOBALS['userId'],
    
                'eventType'    => 'UP',
                'eventId'      => 'userModification',
    
    Damien's avatar
    Damien committed
                'info'         => _USER_UPDATED . " {$data['firstname']} {$data['lastname']}"
    
    Damien's avatar
    Damien committed
            return $response->withStatus(204);
    
    Damien's avatar
    Damien committed
        public function isDeletable(Request $request, Response $response, array $aArgs)
        {
            $error = $this->hasUsersRights(['id' => $aArgs['id'], 'delete' => true, 'himself' => true]);
            if (!empty($error['error'])) {
                return $response->withStatus($error['status'])->withJson(['errors' => $error['error']]);
            }
    
            $user = UserModel::getById(['id' => $aArgs['id'], 'select' => ['firstname', 'lastname', 'user_id']]);
    
            $isListInstanceDeletable = true;
            $isListTemplateDeletable = true;
    
            $listInstanceEntities = [];
            $listInstanceResIds = [];
            $listInstances = ListInstanceModel::getWhenOpenMailsByLogin(['select' => ['listinstance.res_id', 'res_letterbox.destination'], 'login' => $user['user_id'], 'itemMode' => 'dest']);
            foreach ($listInstances as $listInstance) {
    
                if (!ResController::hasRightByResId(['resId' => [$listInstance['res_id']], 'userId' => $GLOBALS['id']])) {
    
    Damien's avatar
    Damien committed
                    $isListInstanceDeletable = false;
                }
                $listInstanceResIds[] = $listInstance['res_id'];
    
                if (!empty($listInstance['destination'])) {
                    $listInstanceEntities[] = $listInstance['destination'];
                }
    
    Damien's avatar
    Damien committed
            }
    
            $listTemplateEntities = [];
    
            $listTemplates = ListTemplateModel::getWithItems([
                'select'    => ['entity_id', 'title'],
                'where'     => ['item_id = ?', 'type = ?', 'item_mode = ?', 'item_type = ?', 'entity_id is not null'],
                'data'      => [$aArgs['id'], 'diffusionList', 'dest', 'user']
    
    Damien's avatar
    Damien committed
            ]);
            $allEntities = EntityModel::getAllEntitiesByUserId(['userId' => $GLOBALS['userId']]);
    
            if (!empty($allEntities)) {
                $allEntities = EntityModel::get(['select' => ['id'], 'where' => ['entity_id in (?)'], 'data' => [$allEntities]]);
                $allEntities = array_column($allEntities, 'id');
            }
    
    Damien's avatar
    Damien committed
            foreach ($listTemplates as $listTemplate) {
    
                if (!in_array($listTemplate['entity_id'], $allEntities)) {
    
    Damien's avatar
    Damien committed
                    $isListTemplateDeletable = false;
                }
                $listTemplateEntities[] = $listTemplate['object_id'];
            }
    
            if (!$isListInstanceDeletable || !$isListTemplateDeletable) {
                $formattedLIEntities = [];
                $listInstanceEntities = array_unique($listInstanceEntities);
                foreach ($listInstanceEntities as $listInstanceEntity) {
                    $entity = Entitymodel::getByEntityId(['select' => ['short_label'], 'entityId' => $listInstanceEntity]);
                    $formattedLIEntities[] = $entity['short_label'];
                }
                $formattedLTEntities = [];
                $listTemplateEntities = array_unique($listTemplateEntities);
                foreach ($listTemplateEntities as $listTemplateEntity) {
                    $entity = Entitymodel::getByEntityId(['select' => ['short_label'], 'entityId' => $listTemplateEntity]);
                    $formattedLTEntities[] = $entity['short_label'];
                }
    
                return $response->withJson(['isDeletable' => false, 'listInstanceEntities' => $formattedLIEntities, 'listTemplateEntities' => $formattedLTEntities]);
            }
    
            $listInstances = [];
            foreach ($listInstanceResIds as $listInstanceResId) {
                $rawListInstances = ListInstanceModel::get([
                    'select'    => ['*'],
                    'where'     => ['res_id = ?', 'difflist_type = ?'],
                    'data'      => [$listInstanceResId, 'entity_id'],
                    'orderBy'   => ['listinstance_id']
                ]);
                $listInstances[] = [
                    'resId'         => $listInstanceResId,
                    'listInstances' => $rawListInstances
                ];
            }
    
            return $response->withJson(['isDeletable' => true, 'listTemplates' => $listTemplates, 'listInstances' => $listInstances]);
        }
    
    
    Damien's avatar
    Damien committed
        public function suspend(Request $request, Response $response, array $aArgs)
        {
            $error = $this->hasUsersRights(['id' => $aArgs['id'], 'delete' => true, 'himself' => true]);
            if (!empty($error['error'])) {
                return $response->withStatus($error['status'])->withJson(['errors' => $error['error']]);
            }
    
            $user = UserModel::getById(['id' => $aArgs['id'], 'select' => ['firstname', 'lastname', 'user_id']]);
    
    
    Damien's avatar
    Damien committed
            $listInstances = ListInstanceModel::getWhenOpenMailsByLogin(['select' => [1], 'login' => $user['user_id'], 'itemMode' => 'dest']);
    
    Damien's avatar
    Damien committed
            if (!empty($listInstances)) {
                return $response->withStatus(403)->withJson(['errors' => 'User is still present in listInstances']);
            }
    
    
            $listTemplates = ListTemplateModel::getWithItems([
    
    Damien's avatar
    Damien committed
                'select'    => [1],
    
                'where'     => ['item_id = ?', 'type = ?', 'item_mode = ?', 'item_type = ?', 'entity_id is not null'],
                'data'      => [$aArgs['id'], 'diffusionList', 'dest', 'user']
    
    Damien's avatar
    Damien committed
            ]);
            if (!empty($listTemplates)) {
                return $response->withStatus(403)->withJson(['errors' => 'User is still present in listTemplates']);
            }
    
            ListInstanceModel::delete([
    
    Damien's avatar
    Damien committed
                'where' => ['item_id = ?', 'difflist_type = ?', 'item_type = ?', 'item_mode != ?'],
                'data'  => [$user['user_id'], 'entity_id', 'user_id', 'dest']
    
    Damien's avatar
    Damien committed
            ]);
            RedirectBasketModel::delete([
                'where' => ['owner_user_id = ? OR actual_user_id = ?'],
                'data'  => [$aArgs['id'], $aArgs['id']]
            ]);
    
            UserModel::update([
                'set'   => [
    
                    'status'   => 'SPD'
    
    Damien's avatar
    Damien committed
                ],
                'where' => ['id = ?'],
                'data'  => [$aArgs['id']]
            ]);
    
            HistoryController::add([
                'tableName'    => 'users',
                'recordId'     => $GLOBALS['userId'],
                'eventType'    => 'DEL',
                'eventId'      => 'userSuppression',
                'info'         => _USER_SUSPENDED . " {$user['firstname']} {$user['lastname']}"
            ]);
    
            return $response->withStatus(204);
        }
    
    
        public function delete(Request $request, Response $response, array $aArgs)
    
            $error = $this->hasUsersRights(['id' => $aArgs['id'], 'delete' => true, 'himself' => true]);
    
            if (!empty($error['error'])) {
                return $response->withStatus($error['status'])->withJson(['errors' => $error['error']]);
            }
    
    
            $user = UserModel::getById(['id' => $aArgs['id'], 'select' => ['firstname', 'lastname', 'user_id']]);
    
    
    Damien's avatar
    Damien committed
            $listInstances = ListInstanceModel::getWhenOpenMailsByLogin(['select' => [1], 'login' => $user['user_id'], 'itemMode' => 'dest']);
    
            if (!empty($listInstances)) {
                return $response->withStatus(403)->withJson(['errors' => 'User is still present in listInstances']);
            }
    
    
            $listTemplates = ListTemplateModel::getWithItems([
    
                'select'    => [1],
    
                'where'     => ['item_id = ?', 'type = ?', 'item_mode = ?', 'item_type = ?', 'entity_id is not null'],
                'data'      => [$aArgs['id'], 'diffusionList', 'dest', 'user']
    
            ]);
            if (!empty($listTemplates)) {
                return $response->withStatus(403)->withJson(['errors' => 'User is still present in listTemplates']);
            }
    
            ListInstanceModel::delete([
    
    Damien's avatar
    Damien committed
                'where' => ['item_id = ?', 'difflist_type = ?', 'item_type = ?', 'item_mode != ?'],
                'data'  => [$user['user_id'], 'entity_id', 'user_id', 'dest']
    
            ListTemplateItemModel::delete([
                'where' => ['item_id = ?', 'item_type = ?'],
                'data'  => [$aArgs['id'], 'user']
    
            ListTemplateModel::deleteNoItemsOnes();
    
            RedirectBasketModel::delete([
                'where' => ['owner_user_id = ? OR actual_user_id = ?'],
                'data'  => [$aArgs['id'], $aArgs['id']]
            ]);
    
            // Delete from groups
            UserGroupModel::delete(['where' => ['user_id = ?'], 'data' => [$aArgs['id']]]);
            UserBasketPreferenceModel::delete([
                'where' => ['user_serial_id = ?'],
                'data'  => [$aArgs['id']]
            ]);
            RedirectBasketModel::delete([
                'where' => ['owner_user_id = ?'],
                'data'  => [$aArgs['id']]
            ]);
    
            // Delete from entities
            UserEntityModel::delete([
                'where' => ['user_id = ?'],
                'data'  => [$user['user_id']]
            ]);
    
    
    Damien's avatar
    Damien committed
            UserModel::delete(['id' => $aArgs['id']]);
    
            HistoryController::add([
                'tableName'    => 'users',
                'recordId'     => $GLOBALS['userId'],
    
                'eventType'    => 'DEL',
                'eventId'      => 'userSuppression',
    
                'info'         => _USER_DELETED . " {$user['firstname']} {$user['lastname']}"
    
    Damien's avatar
    Damien committed
            return $response->withStatus(204);
    
        public function getProfile(Request $request, Response $response)
        {
    
            $user = UserModel::getById(['id' => $GLOBALS['id'], 'select' => ['id', 'user_id', 'firstname', 'lastname', 'phone', 'mail', 'initials', 'preferences', 'external_id']]);
    
            $user['external_id']        = json_decode($user['external_id'], true);
    
            $user['preferences']        = json_decode($user['preferences'], true);
    
            $user['signatures']         = UserSignatureModel::getByUserSerialId(['userSerialid' => $user['id']]);
            $user['emailSignatures']    = UserModel::getEmailSignaturesById(['userId' => $user['user_id']]);
    
            $user['groups']             = UserModel::getGroupsByLogin(['login' => $user['user_id']]);
    
            $user['entities']           = UserModel::getEntitiesByLogin(['login' => $user['user_id']]);
    
            $user['baskets']            = BasketModel::getBasketsByLogin(['login' => $user['user_id']]);
    
            $user['assignedBaskets']    = RedirectBasketModel::getAssignedBasketsByUserId(['userId' => $user['id']]);
            $user['redirectedBaskets']  = RedirectBasketModel::getRedirectedBasketsByUserId(['userId' => $user['id']]);
            $user['regroupedBaskets']   = BasketModel::getRegroupedBasketsByUserId(['userId' => $user['user_id']]);
            $user['passwordRules']      = PasswordModel::getEnabledRules();
            $user['canModifyPassword']  = true;
    
            $user['privileges']         = PrivilegeController::getPrivilegesByUser(['userId' => $user['id']]);
    
            $userFollowed = UserFollowedResourceModel::get(['select' => ['count(1) as nb'], 'where' => ['user_id = ?'], 'data' => [$GLOBALS['id']]]);
            $user['nbFollowedResources'] = $userFollowed[0]['nb'];
    
            $loggingMethod = CoreConfigModel::getLoggingMethod();
    
            if (in_array($loggingMethod['id'], self::ALTERNATIVES_CONNECTIONS_METHODS)) {
    
                $user['canModifyPassword'] = false;
            }
    
    
            foreach ($user['baskets'] as $key => $basket) {
                if (!$basket['allowed']) {
                    unset($user['baskets'][$key]);
                }
            }
            $user['baskets'] = array_values($user['baskets']);
    
    
            return $response->withJson($user);
        }
    
        public function updateProfile(Request $request, Response $response)
    
            $body = $request->getParsedBody();
    
            if (!Validator::stringType()->notEmpty()->validate($body['firstname'])) {
                return $response->withStatus(400)->withJson(['errors' => 'Body firstname is empty or not a string']);
            } elseif (!Validator::stringType()->notEmpty()->validate($body['lastname'])) {
                return $response->withStatus(400)->withJson(['errors' => 'Body lastname is empty or not a string']);
            } elseif (!Validator::stringType()->notEmpty()->validate($body['mail']) || !filter_var($body['mail'], FILTER_VALIDATE_EMAIL)) {
                return $response->withStatus(400)->withJson(['errors' => 'Body mail is empty or not a valid email']);
            } elseif (!empty($body['phone']) && !preg_match("/\+?((|\ |\.|\(|\)|\-)?(\d)*)*\d/", $body['phone'])) {
                return $response->withStatus(400)->withJson(['errors' => 'Body phone is not a valid phone number']);
    
    Damien's avatar
    Damien committed
            UserModel::update([
                'set'   => [
    
                    'firstname'     => $body['firstname'],
                    'lastname'      => $body['lastname'],
                    'mail'          => $body['mail'],
                    'phone'         => $body['phone'],
    
    Damien's avatar
    Damien committed
                ],
                'where' => ['id = ?'],
    
                'data'  => [$GLOBALS['id']]
    
    Damien's avatar
    Damien committed
            ]);
    
            HistoryController::add([
                'tableName'    => 'users',
                'recordId'     => $GLOBALS['userId'],
                'eventType'    => 'UP',
                'eventId'      => 'userModification',
                'info'         => _USER_UPDATED . " {$body['firstname']} {$body['lastname']}"
            ]);
    
    
            return $response->withStatus(204);
    
        public function updateCurrentUserPreferences(Request $request, Response $response)
        {
            $body = $request->getParsedBody();
    
    
            $user = UserModel::getById(['id' => $GLOBALS['id'], 'select' => ['preferences', 'firstname', 'lastname']]);
    
            $preferences = json_decode($user['preferences'], true);
    
            if (!empty($body['documentEdition'])) {
                if (!in_array($body['documentEdition'], DocumentEditorController::DOCUMENT_EDITION_METHODS)) {
                    return $response->withStatus(400)->withJson(['errors' => 'Body preferences[documentEdition] is not allowed']);
                }
                $preferences['documentEdition'] = $body['documentEdition'];
            }
            if (!empty($body['homeGroups'])) {
                $preferences['homeGroups'] = $body['homeGroups'];
            }
    
            UserModel::update([
                'set'   => [
                    'preferences'   => json_encode($preferences)
                ],
                'where' => ['id = ?'],
                'data'  => [$GLOBALS['id']]
            ]);
    
    
            HistoryController::add([
                'tableName'    => 'users',
                'recordId'     => $GLOBALS['userId'],
                'eventType'    => 'UP',
                'eventId'      => 'userModification',
                'info'         => _USER_PREFERENCE_UPDATED . " {$user['firstname']} {$user['lastname']}"
            ]);
    
    
            return $response->withStatus(204);
        }
    
    
        public function updatePassword(Request $request, Response $response, array $aArgs)
    
            $error = $this->hasUsersRights(['id' => $aArgs['id'], 'himself' => true]);
            if (!empty($error['error'])) {
                return $response->withStatus($error['status'])->withJson(['errors' => $error['error']]);
            }
    
            $body = $request->getParsedBody();
    
            $check = Validator::stringType()->notEmpty()->validate($body['currentPassword']);
            $check = $check && Validator::stringType()->notEmpty()->validate($body['newPassword']);
            $check = $check && Validator::stringType()->notEmpty()->validate($body['reNewPassword']);
    
            if (!$check) {
                return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
    
            $user = UserModel::getById(['id' => $aArgs['id'], 'select' => ['user_id', 'loginmode']]);
            if ($user['loginmode'] != 'restMode' && $user['user_id'] != $GLOBALS['userId']) {
                return $response->withStatus(403)->withJson(['errors' => 'Not allowed']);
            }
    
            if ($body['newPassword'] != $body['reNewPassword']) {
    
                return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
    
            } elseif (!AuthenticationModel::authentication(['userId' => $user['user_id'], 'password' => $body['currentPassword']])) {
    
                return $response->withStatus(401)->withJson(['errors' => _WRONG_PSW]);
    
            } elseif (!PasswordController::isPasswordValid(['password' => $body['newPassword']])) {
    
                return $response->withStatus(400)->withJson(['errors' => 'Password does not match security criteria']);
    
            } elseif (!PasswordModel::isPasswordHistoryValid(['password' => $body['newPassword'], 'userSerialId' => $aArgs['id']])) {
    
    Damien's avatar
    Damien committed
                return $response->withStatus(400)->withJson(['errors' => _ALREADY_USED_PSW]);
    
            UserModel::updatePassword(['id' => $aArgs['id'], 'password' => $body['newPassword']]);
            PasswordModel::setHistoryPassword(['userSerialId' => $aArgs['id'], 'password' => $body['newPassword']]);
    
            HistoryController::add([
                'tableName'    => 'users',
                'recordId'     => $user['user_id'],
                'eventType'    => 'UP',
                'eventId'      => 'userModification',
                'info'         => _USER_PASSWORD_UPDATED
            ]);
    
    
    Damien's avatar
    Damien committed
            return $response->withJson(['success' => 'success']);
    
        public function setRedirectedBaskets(Request $request, Response $response, array $aArgs)
        {
            $error = $this->hasUsersRights(['id' => $aArgs['id'], 'himself' => true]);
            if (!empty($error['error'])) {
                return $response->withStatus($error['status'])->withJson(['errors' => $error['error']]);
    
    Damien's avatar
    Damien committed
            DatabaseModel::beginTransaction();
    
            foreach ($data as $key => $value) {
    
    Damien's avatar
    Damien committed
                if (empty($value['actual_user_id']) || empty($value['basket_id']) || empty($value['group_id'])) {
                    DatabaseModel::rollbackTransaction();
    
                    return $response->withStatus(400)->withJson(['errors' => 'Some data are empty']);
    
                $userBasketPreference = UserBasketPreferenceModel::get([
    
                    'where'  => ['basket_id =?', 'group_serial_id = ?', 'user_serial_id = ?'],
                    'data'   => [$value['basket_id'], $value['group_id'], $aArgs['id']]
                ]);
    
                if (empty($userBasketPreference)) {
                    unset($data[$key]);
                    continue;
                }
    
    
    Damien's avatar
    Damien committed
                $check = UserModel::getById(['id' => $value['actual_user_id'], 'select' => ['1']]);
    
                if (empty($check)) {
    
    Damien's avatar
    Damien committed
                    DatabaseModel::rollbackTransaction();
    
                    return $response->withStatus(400)->withJson(['errors' => 'User not found']);
    
    Damien's avatar
    Damien committed
                $check = RedirectBasketModel::get([
                    'select' => [1],
                    'where'  => ['actual_user_id = ?', 'owner_user_id = ?', 'basket_id = ?', 'group_id = ?'],
                    'data'   => [$value['actual_user_id'], $aArgs['id'], $value['basket_id'], $value['group_id']]
                ]);
    
                if (!empty($check)) {
                    DatabaseModel::rollbackTransaction();
                    return $response->withStatus(400)->withJson(['errors' => 'Redirection already exist']);
                }
    
    
    Damien's avatar
    Damien committed
                if (!empty($value['originalOwner'])) {
                    RedirectBasketModel::update([
                        'actual_user_id'    => $value['actual_user_id'],
                        'basket_id'         => $value['basket_id'],
                        'group_id'          => $value['group_id'],
                        'owner_user_id'     => $value['originalOwner']
    
                    HistoryController::add([
    
    Damien's avatar
    Damien committed
                        'tableName'    => 'redirected_baskets',
    
                        'recordId'     => $GLOBALS['userId'],
                        'eventType'    => 'UP',
                        'eventId'      => 'basketRedirection',
    
    Damien's avatar
    Damien committed
                        'info'         => _BASKET_REDIRECTION . " {$value['basket_id']} {$value['actual_user_id']}"
    
                foreach ($data as $value) {
    
    Damien's avatar
    Damien committed
                    RedirectBasketModel::create([
                        'actual_user_id'    => $value['actual_user_id'],
                        'basket_id'         => $value['basket_id'],
                        'group_id'          => $value['group_id'],
                        'owner_user_id'     => $aArgs['id']
    
                    HistoryController::add([
    
    Damien's avatar
    Damien committed
                        'tableName'    => 'redirected_baskets',
    
                        'recordId'     => $GLOBALS['userId'],
                        'eventType'    => 'UP',
                        'eventId'      => 'basketRedirection',
    
    Damien's avatar
    Damien committed
                        'info'         => _BASKET_REDIRECTION . " {$value['basket_id']} {$aArgs['id']} => {$value['actual_user_id']}"
    
    Damien's avatar
    Damien committed
            DatabaseModel::commitTransaction();
    
            $user = UserModel::getById(['id' => $aArgs['id'], 'select' => ['user_id']]);
    
    
            $userBaskets = BasketModel::getBasketsByLogin(['login' => $user['user_id']]);
    
            if ($GLOBALS['userId'] == $user['user_id']) {
                foreach ($userBaskets as $key => $basket) {
                    if (!$basket['allowed']) {
                        unset($userBaskets[$key]);
                    }
                }
                $userBaskets = array_values($userBaskets);
            }
    
    
            return $response->withJson([
    
    Damien's avatar
    Damien committed
                'redirectedBaskets' => RedirectBasketModel::getRedirectedBasketsByUserId(['userId' => $aArgs['id']]),
    
                'baskets'           => $userBaskets
    
    Damien's avatar
    Damien committed
        public function deleteRedirectedBasket(Request $request, Response $response, array $aArgs)
    
            $error = $this->hasUsersRights(['id' => $aArgs['id'], 'himself' => true]);
            if (!empty($error['error'])) {
                return $response->withStatus($error['status'])->withJson(['errors' => $error['error']]);
            }
    
    
            $data = $request->getQueryParams();
    
    
            DatabaseModel::beginTransaction();
    
    
            $check = Validator::notEmpty()->arrayType()->validate($data['redirectedBasketIds']);
            if (!$check) {
    
                DatabaseModel::rollbackTransaction();
    
                return $response->withStatus(400)->withJson(['errors' => 'RedirectedBasketIds is empty or not an array']);
    
    Damien's avatar
    Damien committed
            $user = UserModel::getById(['id' => $aArgs['id'], 'select' => ['user_id']]);
    
            if (empty($user)) {
                DatabaseModel::rollbackTransaction();
                return $response->withStatus(400)->withJson(['errors' => 'User not found']);
            }
    
    
    Florian Azizian's avatar
    Florian Azizian committed
            foreach ($data['redirectedBasketIds'] as $redirectedBasketId) {
    
                $redirectedBasket = RedirectBasketModel::get(['select' => ['actual_user_id', 'owner_user_id', 'basket_id'], 'where' => ['id = ?'], 'data' => [$redirectedBasketId]]);
                if (empty($redirectedBasket[0]) || ($redirectedBasket[0]['actual_user_id'] != $aArgs['id'] && $redirectedBasket[0]['owner_user_id'] != $aArgs['id'])) {
    
                    DatabaseModel::rollbackTransaction();
    
                    return $response->withStatus(403)->withJson(['errors' => 'Redirected basket out of perimeter']);
                }
    
                RedirectBasketModel::delete(['where' => ['id = ?'], 'data' => [$redirectedBasketId]]);
    
                HistoryController::add([
                    'tableName'    => 'redirected_baskets',
                    'recordId'     => $GLOBALS['userId'],
                    'eventType'    => 'DEL',
                    'eventId'      => 'basketRedirection',
                    'info'         => _BASKET_REDIRECTION_SUPPRESSION . " {$user['user_id']} : " . $redirectedBasket[0]['basket_id']
                ]);
            }
    
            DatabaseModel::commitTransaction();
    
    
            $userBaskets = BasketModel::getBasketsByLogin(['login' => $user['user_id']]);
    
            if ($GLOBALS['userId'] == $user['user_id']) {
                foreach ($userBaskets as $key => $basket) {
                    if (!$basket['allowed']) {
                        unset($userBaskets[$key]);
                    }
                }
                $userBaskets = array_values($userBaskets);
            }
    
    
            return $response->withJson([
    
                'baskets'   => $userBaskets
    
        public function getStatusByUserId(Request $request, Response $response, array $aArgs)
        {
    
            if (!PrivilegeController::hasPrivilege(['privilegeId' => 'admin_users', 'userId' => $GLOBALS['id']])) {
    
                return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
            }
    
    Vinciane's avatar
    Vinciane committed
            $user = UserModel::getByLowerLogin(['login' => $aArgs['userId'], 'select' => ['status']]);
    
    Vinciane's avatar
    Vinciane committed
            if (empty($user)) {
    
                return $response->withJson(['status' => null]);
    
    Vinciane's avatar
    Vinciane committed
            }
    
    Vinciane's avatar
    Vinciane committed
            return $response->withJson(['status' => $user['status']]);
    
        public function updateStatus(Request $request, Response $response, array $aArgs)
        {
    
    Damien's avatar
    Damien committed
            $error = $this->hasUsersRights(['id' => $aArgs['id'], 'himself' => true]);
            if (!empty($error['error'])) {
                return $response->withStatus($error['status'])->withJson(['errors' => $error['error']]);
            }
    
            $data = $request->getParams();
    
    
            $check = Validator::stringType()->notEmpty()->validate($data['status']);
    
            $check = $check && ($data['status'] == 'OK' || $data['status'] == 'ABS');
            if (!$check) {
                return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
            }
    
            UserModel::updateStatus(['id' => $aArgs['id'], 'status' => $data['status']]);
    
            $user = UserModel::getById(['id' => $aArgs['id'], 'select' => ['user_id', 'firstname', 'lastname']]);
            HistoryController::add([
                'tableName'    => 'users',
                'recordId'     => $user['user_id'],
                'eventType'    => 'RET',
                'eventId'      => 'userabs',
    
    Damien's avatar
    Damien committed
                'info'         => "{$user['firstname']} {$user['lastname']} " ._BACK_FROM_VACATION
    
            return $response->withJson(['user' => UserModel::getById(['id' => $aArgs['id'], 'select' => ['status']])]);
    
        public function getImageContent(Request $request, Response $response, array $aArgs)
    
            if (!Validator::intVal()->validate($aArgs['id']) || !Validator::intVal()->validate($aArgs['signatureId'])) {
                return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
            }
    
    
            if (!PrivilegeController::hasPrivilege(['privilegeId' => 'view_personal_data', 'userId' => $GLOBALS['id']])
                && $aArgs['id'] != $GLOBALS['id']) {
                return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
            }
    
    
            $error = $this->hasUsersRights(['id' => $aArgs['id'], 'himself' => true]);
            if (!empty($error['error'])) {
                return $response->withStatus($error['status'])->withJson(['errors' => $error['error']]);
            }
    
            $signatures = UserSignatureModel::get([
                'select'    => ['signature_path', 'signature_file_name'],
                'where'     => ['user_serial_id = ?', 'id = ?'],
                'data'      => [$aArgs['id'], $aArgs['signatureId']]
            ]);
            if (empty($signatures[0])) {
                return $response->withStatus(400)->withJson(['errors' => 'Signature does not exist']);
            }
    
    
            $docserver = DocserverModel::getCurrentDocserver(['typeId' => 'TEMPLATES', 'collId' => 'templates', 'select' => ['path_template']]);
    
            if (empty($docserver['path_template']) || !file_exists($docserver['path_template'])) {
    
                return [];
            }
    
            $pathToSignature = $docserver['path_template'] . str_replace('#', '/', $signatures[0]['signature_path']) . $signatures[0]['signature_file_name'];
            $image = file_get_contents($pathToSignature);
            if ($image === false) {
                return $response->withStatus(404)->withJson(['errors' => 'Signature not found on docserver']);
            }
    
    
    Damien's avatar
    Damien committed
            $finfo    = new \finfo(FILEINFO_MIME_TYPE);
            $mimeType = $finfo->buffer($image);
    
    
            $response->write($image);
    
    
    Damien's avatar
    Damien committed
            return $response->withHeader('Content-Type', $mimeType);
    
        public function addSignature(Request $request, Response $response, array $aArgs)
    
            if (!PrivilegeController::hasPrivilege(['privilegeId' => 'manage_personal_data', 'userId' => $GLOBALS['id']])
                && $aArgs['id'] != $GLOBALS['id']) {
                return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
            }
    
    
    Damien's avatar
    Damien committed
            $error = $this->hasUsersRights(['id' => $aArgs['id'], 'himself' => true]);
    
            if (!empty($error['error'])) {
                return $response->withStatus($error['status'])->withJson(['errors' => $error['error']]);
            }
    
    
            $data = $request->getParams();
    
    
            if (!$this->checkNeededParameters(['data' => $data, 'needed' => ['base64', 'name', 'label']])) {
    
                return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
            }
    
    
            $file     = base64_decode($data['base64']);
    
            $tmpName  = "tmp_file_{$aArgs['id']}_" .rand(). "_{$data['name']}";
    
            $finfo    = new \finfo(FILEINFO_MIME_TYPE);
            $mimeType = $finfo->buffer($file);
    
            $type     = explode('/', $mimeType);
            $ext      = strtoupper(substr($data['name'], strrpos($data['name'], '.') + 1));
    
    
            $fileAccepted  = StoreController::isFileAllowed(['extension' => $ext, 'type' => $mimeType]);
    
            if (!$fileAccepted || $type[0] != 'image') {
    
                return $response->withStatus(400)->withJson(['errors' => _WRONG_FILE_TYPE]);
    
            } elseif ($size > 2000000) {
    
                return $response->withStatus(400)->withJson(['errors' => _MAX_SIZE_UPLOAD_REACHED . ' (2 MB)']);
    
    Damien's avatar
    Damien committed
            file_put_contents(CoreConfigModel::getTmpPath() . $tmpName, $file);
    
            $storeInfos = DocserverController::storeResourceOnDocServer([
    
                'collId'            => 'templates',
                'docserverTypeId'   => 'TEMPLATES',
    
    Damien's avatar
    Damien committed
                'encodedResource'   => base64_encode($file),
                'format'            => $ext
    
    
            if (!file_exists($storeInfos['path_template']. str_replace('#', '/', $storeInfos['destination_dir']) .$storeInfos['file_destination_name'])) {
    
    Damien's avatar
    Damien committed
                return $response->withStatus(500)->withJson(['errors' => $storeInfos['error'] .' '. _PATH_OF_DOCSERVER_UNAPPROACHABLE]);
    
    Damien's avatar
    Damien committed
            UserSignatureModel::create([
    
                'signatureLabel'    => $data['label'],
                'signaturePath'     => $storeInfos['destination_dir'],
                'signatureFileName' => $storeInfos['file_destination_name'],
            ]);
    
    
            return $response->withJson([
    
                'signatures' => UserSignatureModel::getByUserSerialId(['userSerialid' => $aArgs['id']])
    
        public function updateSignature(Request $request, Response $response, array $aArgs)
    
            if (!PrivilegeController::hasPrivilege(['privilegeId' => 'manage_personal_data', 'userId' => $GLOBALS['id']])
                && $aArgs['id'] != $GLOBALS['id']) {
                return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
            }
    
    
    Damien's avatar
    Damien committed
            $error = $this->hasUsersRights(['id' => $aArgs['id'], 'himself' => true]);
    
            if (!empty($error['error'])) {
                return $response->withStatus($error['status'])->withJson(['errors' => $error['error']]);
            }
    
    
            $data = $request->getParams();
    
            if (!$this->checkNeededParameters(['data' => $data, 'needed' => ['label']])) {
                return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
            }
    
    
    Damien's avatar
    Damien committed
            UserSignatureModel::update([
    
                'signatureId'   => $aArgs['signatureId'],
                'userSerialId'  => $aArgs['id'],
                'label'         => $data['label']
    
                'signature' => UserSignatureModel::getById(['id' => $aArgs['signatureId']])
    
        public function deleteSignature(Request $request, Response $response, array $aArgs)
    
            if (!PrivilegeController::hasPrivilege(['privilegeId' => 'manage_personal_data', 'userId' => $GLOBALS['id']])
                && $aArgs['id'] != $GLOBALS['id']) {
                return $response->withStatus(403)->withJson(['errors' => 'Service forbidden']);
            }
    
    
    Damien's avatar
    Damien committed
            $error = $this->hasUsersRights(['id' => $aArgs['id'], 'himself' => true]);
    
            if (!empty($error['error'])) {
                return $response->withStatus($error['status'])->withJson(['errors' => $error['error']]);