Skip to content
Snippets Groups Projects
UserController.php 16.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • Florian Azizian's avatar
    Florian Azizian committed
    <?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;
    
    use Docserver\controllers\DocserverController;
    use Docserver\models\DocserverModel;
    
    Damien's avatar
    Damien committed
    use History\controllers\HistoryController;
    
    Florian Azizian's avatar
    Florian Azizian committed
    use Respect\Validation\Validator;
    use Slim\Http\Request;
    use Slim\Http\Response;
    
    use SrcCore\controllers\PasswordController;
    use SrcCore\models\AuthenticationModel;
    
    use SrcCore\models\ValidatorModel;
    use User\models\UserGroupModel;
    
    Florian Azizian's avatar
    Florian Azizian committed
    use User\models\UserModel;
    
    class UserController
    {
    
    Damien's avatar
    Damien committed
        public function get(Request $request, Response $response)
        {
    
    Damien's avatar
    Damien committed
            $queryParams = $request->getQueryParams();
    
    Damien's avatar
    Damien committed
            if (!empty($queryParams['mode']) && $queryParams['mode'] == 'rest') {
    
                if (!UserController::hasPrivilege(['userId' => $GLOBALS['id'], 'privilege' => 'manage_rest_users'])) {
                    return $response->withStatus(403)->withJson(['errors' => 'Privilege forbidden']);
                }
                $queryData = ['rest'];
            } else {
                if (!UserController::hasPrivilege(['userId' => $GLOBALS['id'], 'privilege' => 'manage_users'])) {
                    return $response->withStatus(403)->withJson(['errors' => 'Privilege forbidden']);
                }
                $queryData = ['standard'];
    
    Damien's avatar
    Damien committed
            $users = UserModel::get([
    
    Damien's avatar
    Damien committed
                'select'    => ['id', 'login', 'firstname', 'lastname', 'email'],
    
    Damien's avatar
    Damien committed
                'where'     => ['mode = ?'],
    
                'data'      => $queryData,
    
    Damien's avatar
    Damien committed
                'orderBy'   => ['lastname', 'firstname']
    
    Damien's avatar
    Damien committed
            ]);
    
            return $response->withJson(['users' => $users]);
        }
    
    
        public function getById(Request $request, Response $response, array $args)
        {
    
            if ($GLOBALS['id'] != $args['id'] && !UserController::hasPrivilege(['userId' => $GLOBALS['id'], 'privilege' => 'manage_users'])) {
                return $response->withStatus(403)->withJson(['errors' => 'Privilege forbidden']);
    
    Florian Azizian's avatar
    Florian Azizian committed
            $user =  UserController::getUserInformationsById(['id' => $args['id']]);
    
            HistoryController::add([
                'code'          => 'OK',
                'objectType'    => 'users',
                'objectId'      => $args['id'],
                'type'          => 'VIEW',
                'message'       => "User viewed : " . $user['firstname'] . ' ' . $user['lastname']
            ]);
    
            return $response->withJson(['user' => $user]);
    
        public function create(Request $request, Response $response)
        {
    
            if (!UserController::hasPrivilege(['userId' => $GLOBALS['id'], 'privilege' => 'manage_users'])) {
                return $response->withStatus(403)->withJson(['errors' => 'Privilege forbidden']);
    
    Damien's avatar
    Damien committed
            $body = $request->getParsedBody();
    
            if (empty($body)) {
                return $response->withStatus(400)->withJson(['errors' => 'Body is not set or empty']);
            } elseif (!Validator::stringType()->notEmpty()->validate($body['login'])) {
                return $response->withStatus(400)->withJson(['errors' => 'Body login is empty or not a string']);
            } elseif (!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']);
    
    Damien's avatar
    Damien committed
            } elseif (empty($body['email']) || !filter_var($body['email'], FILTER_VALIDATE_EMAIL)) {
    
    Damien's avatar
    Damien committed
                return $response->withStatus(400)->withJson(['errors' => 'Body email is empty or not a valid email']);
    
    Damien's avatar
    Damien committed
            $existingUser = UserModel::getByLogin(['login' => $body['login'], 'select' => [1]]);
    
            if (!empty($existingUser)) {
    
    Damien's avatar
    Damien committed
                return $response->withStatus(400)->withJson(['errors' => 'Login already exists']);
    
            }
    
            $logingModes = ['standard', 'rest'];
    
    Damien's avatar
    Damien committed
            if (empty($body['mode']) || !in_array($body['mode'], $logingModes)) {
                $body['mode'] = 'standard';
    
    Damien's avatar
    Damien committed
            $body['picture'] = empty($body['picture']) ? null : $body['picture'];
    
    Damien's avatar
    Damien committed
            $id = UserModel::create($body);
    
    
            HistoryController::add([
    
    Damien's avatar
    Damien committed
                'code'          => 'OK',
                'objectType'    => 'users',
                'objectId'      => $id,
                'type'          => 'CREATION',
                'message'       => "User added : {$body['firstname']} {$body['lastname']}"
    
    Damien's avatar
    Damien committed
            return $response->withJson(['id' => $id]);
    
        public function update(Request $request, Response $response, array $args)
        {
    
            if ($GLOBALS['id'] != $args['id'] && !UserController::hasPrivilege(['userId' => $GLOBALS['id'], 'privilege' => 'manage_users'])) {
                return $response->withStatus(403)->withJson(['errors' => 'Privilege forbidden']);
    
    Damien's avatar
    Damien committed
            $body = $request->getParsedBody();
            $check = Validator::stringType()->notEmpty()->validate($body['firstname']);
            $check = $check && Validator::stringType()->notEmpty()->validate($body['lastname']);
    
            if (!$check) {
                return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
            }
    
    
    Damien's avatar
    Damien committed
            $check = Validator::arrayType()->notEmpty()->validate($body['preferences']);
            $check = $check && Validator::stringType()->notEmpty()->validate($body['preferences']['writingMode']);
            $check = $check && Validator::intType()->notEmpty()->validate($body['preferences']['writingSize']);
            $check = $check && Validator::stringType()->notEmpty()->validate($body['preferences']['writingColor']);
    
    Damien's avatar
    Damien committed
            if (!$check) {
                return $response->withStatus(400)->withJson(['errors' => 'Missing parameter in user preferences data']);
            }
    
    
    Damien's avatar
    Damien committed
            $body['preferences'] = json_encode($body['preferences']);
            if (!is_string($body['preferences'])) {
    
    Damien's avatar
    Damien committed
                return $response->withStatus(400)->withJson(['errors' => 'Wrong format for user preferences data']);
            }
    
    
    Damien's avatar
    Damien committed
            if (!empty($body['picture'])) {
    
    Damien's avatar
    Damien committed
                $infoContent = '';
    
    Damien's avatar
    Damien committed
                if (preg_match('/^data:image\/(\w+);base64,/', $body['picture'])) {
                    $infoContent = substr($body['picture'], 0, strpos($body['picture'], ',') + 1);
                    $body['picture'] = substr($body['picture'], strpos($body['picture'], ',') + 1);
    
    Damien's avatar
    Damien committed
                }
    
    Damien's avatar
    Damien committed
                $picture    = base64_decode($body['picture']);
    
                $finfo      = new \finfo(FILEINFO_MIME_TYPE);
                $mimeType   = $finfo->buffer($picture);
                $type       = explode('/', $mimeType);
    
                if ($type[0] != 'image') {
                    return $response->withStatus(400)->withJson(['errors' => 'Picture is not an image']);
                }
    
    Damien's avatar
    Damien committed
    
    
    Damien's avatar
    Damien committed
                if (!empty($body['pictureOrientation'])) {
    
    Damien's avatar
    Damien committed
                    $imagick = new \Imagick();
    
    Damien's avatar
    Damien committed
                    $imagick->readImageBlob(base64_decode($body['picture']));
                    $imagick->rotateImage(new \ImagickPixel(), $body['pictureOrientation']);
                    $body['picture'] = base64_encode($imagick->getImageBlob());
    
    Damien's avatar
    Damien committed
                }
    
    Damien's avatar
    Damien committed
                $body['picture'] = $infoContent . $body['picture'];
    
    Damien's avatar
    Damien committed
            }
    
    Damien's avatar
    Damien committed
            $set = [
    
    Damien's avatar
    Damien committed
                'firstname'     => $body['firstname'],
                'lastname'      => $body['lastname'],
                'preferences'   => $body['preferences']
    
    Damien's avatar
    Damien committed
            ];
    
    Damien's avatar
    Damien committed
            if (!empty($body['picture'])) {
                $set['picture'] = $body['picture'];
    
    Damien's avatar
    Damien committed
            }
    
            UserModel::update([
                'set'   => $set,
                'where' => ['id = ?'],
                'data'  => [$args['id']]
            ]);
    
    Damien's avatar
    Damien committed
            HistoryController::add([
    
    Damien's avatar
    Damien committed
                'code'          => 'OK',
                'objectType'    => 'users',
                'objectId'      => $args['id'],
                'type'          => 'MODIFICATION',
                'message'       => "User updated : {$body['firstname']} {$body['lastname']}"
    
    Damien's avatar
    Damien committed
            return $response->withJson(['user' => UserController::getUserInformationsById(['id' => $args['id']])]);
    
        }
    
        public function updatePassword(Request $request, Response $response, array $args)
        {
            $data = $request->getParams();
    
    Damien's avatar
    Damien committed
            if (!Validator::stringType()->notEmpty()->validate($data['newPassword'])) {
    
                return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
            }
    
    
            $user = UserModel::getById(['select' => ['login', 'mode'], 'id' => $args['id']]);
    
            if ($GLOBALS['id'] != $args['id']) {
                if ($user['mode'] == 'rest' && !UserController::hasPrivilege(['userId' => $GLOBALS['id'], 'privilege' => 'manage_rest_users'])) {
                    return $response->withStatus(403)->withJson(['errors' => 'Privilege forbidden']);
                } elseif ($user['mode'] == 'standard' && !UserController::hasPrivilege(['userId' => $GLOBALS['id'], 'privilege' => 'manage_users'])) {
                    return $response->withStatus(403)->withJson(['errors' => 'Privilege forbidden']);
                }
            }
    
            if ($user['mode'] == 'standard') {
                if ($data['newPassword'] != $data['passwordConfirmation']) {
                    return $response->withStatus(400)->withJson(['errors' => 'New password does not match password confirmation']);
    
                } elseif (empty($data['currentPassword']) || !AuthenticationModel::authentication(['login' => $user['login'], 'password' => $data['currentPassword']])) {
    
                    return $response->withStatus(401)->withJson(['errors' => 'Wrong Password']);
                }
            }
            if (!PasswordController::isPasswordValid(['password' => $data['newPassword']])) {
    
                return $response->withStatus(400)->withJson(['errors' => 'Password does not match security criteria']);
            }
    
            UserModel::updatePassword(['id' => $args['id'], 'password' => $data['newPassword']]);
    
    
            if ($user['mode'] == 'standard') {
                AuthenticationModel::revokeCookie(['userId' => $args['id']]);
            }
    
    Damien's avatar
    Damien committed
            HistoryController::add([
    
    Damien's avatar
    Damien committed
                'code'          => 'OK',
                'objectType'    => 'users',
                'objectId'      => $args['id'],
                'type'          => 'MODIFICATION',
                'message'       => "User password updated"
    
            return $response->withJson(['success' => 'success']);
        }
    
    
        public function getSignatures(Request $request, Response $response, array $args)
    
    Florian Azizian's avatar
    Florian Azizian committed
        {
    
            if ($GLOBALS['id'] != $args['id'] && !UserController::hasPrivilege(['userId' => $GLOBALS['id'], 'privilege' => 'manage_users'])) {
    
                return $response->withStatus(403)->withJson(['errors' => 'Privilege forbidden']);
    
    Damien's avatar
    Damien committed
            $data = $request->getQueryParams();
            if (empty($data['offset']) || !is_numeric($data['offset'])) {
                $data['offset'] = 0;
            }
            if (empty($data['limit']) || !is_numeric($data['limit'])) {
                $data['limit'] = 0;
            }
    
            $rawSignatures = UserModel::getSignatures([
    
    Damien's avatar
    Damien committed
                'select'    => ['id', 'path', 'filename', 'fingerprint'],
    
    Damien's avatar
    Damien committed
                'where'     => ['user_id = ?'],
                'data'      => [$args['id']],
    
    Damien's avatar
    Damien committed
                'orderBy'   => ['id DESC'],
    
    Damien's avatar
    Damien committed
                'offset'    => (int)$data['offset'],
                'limit'     => (int)$data['limit']
            ]);
    
            $docserver = DocserverModel::getByType(['type' => 'SIGNATURE', 'select' => ['path']]);
            if (empty($docserver['path']) || !file_exists($docserver['path'])) {
                return $response->withStatus(400)->withJson(['errors' => 'Docserver does not exist']);
    
            $signatures = [];
            foreach ($rawSignatures as $signature) {
                $pathToSignature = $docserver['path'] . $signature['path'] . $signature['filename'];
                if (file_exists($pathToSignature)) {
                    $fingerprint = DocserverController::getFingerPrint(['path' => $pathToSignature]);
                    if ($signature['fingerprint'] == $fingerprint) {
                        $signatures[] = [
    
    Damien's avatar
    Damien committed
                            'id'                => $signature['id'],
                            'encodedSignature'  => base64_encode(file_get_contents($pathToSignature))
    
                        ];
                    } else {
                        //TODO LOG
    
    Florian Azizian's avatar
    Florian Azizian committed
                    }
                } else {
    
                    //TODO LOG
    
            return $response->withJson(['signatures' => $signatures]);
    
    Florian Azizian's avatar
    Florian Azizian committed
        }
    
    Damien's avatar
    Damien committed
    
        public function createSignature(Request $request, Response $response, array $args)
        {
    
            if ($GLOBALS['id'] != $args['id'] && !UserController::hasPrivilege(['userId' => $GLOBALS['id'], 'privilege' => 'manage_users'])) {
    
                return $response->withStatus(403)->withJson(['errors' => 'Privilege forbidden']);
    
    Damien's avatar
    Damien committed
            }
    
            $data = $request->getParams();
    
            $check = Validator::notEmpty()->validate($data['encodedSignature']);
            $check = $check && Validator::stringType()->notEmpty()->validate($data['format']);
            if (!$check) {
                return $response->withStatus(400)->withJson(['errors' => 'Bad Request']);
            }
    
            $storeInfos = DocserverController::storeResourceOnDocServer([
                'encodedFile'       => $data['encodedSignature'],
                'format'            => $data['format'],
                'docserverType'     => 'SIGNATURE'
            ]);
    
            if (!empty($storeInfos['errors'])) {
                return $response->withStatus(500)->withJson(['errors' => $storeInfos['errors']]);
            }
    
    
    Damien's avatar
    Damien committed
            $id = UserModel::createSignature([
    
    Damien's avatar
    Damien committed
                'userId'        => $args['id'],
                'path'          => $storeInfos['path'],
                'filename'      => $storeInfos['filename'],
                'fingerprint'   => $storeInfos['fingerprint'],
            ]);
    
    
    Damien's avatar
    Damien committed
            HistoryController::add([
    
    Damien's avatar
    Damien committed
                'code'          => 'OK',
                'objectType'    => 'signatures',
                'objectId'      => $id,
                'type'          => 'CREATION',
                'message'       => "Signature added",
    
    Damien's avatar
    Damien committed
                'data'          => ['userId' => $args['id']]
    
    Damien's avatar
    Damien committed
            return $response->withJson(['signatureId' => $id]);
    
    Damien's avatar
    Damien committed
        }
    
        public function deleteSignature(Request $request, Response $response, array $args)
        {
    
            if ($GLOBALS['id'] != $args['id'] && !UserController::hasPrivilege(['userId' => $GLOBALS['id'], 'privilege' => 'manage_users'])) {
    
                return $response->withStatus(403)->withJson(['errors' => 'Privilege forbidden']);
    
    Damien's avatar
    Damien committed
            }
    
            UserModel::deleteSignature(['where' => ['user_id = ?', 'id = ?'], 'data' => [$args['id'], $args['signatureId']]]);
    
    
    Damien's avatar
    Damien committed
            HistoryController::add([
    
    Damien's avatar
    Damien committed
                'code'          => 'OK',
                'objectType'    => 'signatures',
                'objectId'      => $args['signatureId'],
                'type'          => 'SUPPRESSION',
                'message'       => "Signature deleted",
    
    Damien's avatar
    Damien committed
                'data'          => ['userId' => $args['id']]
    
    Damien's avatar
    Damien committed
            return $response->withJson(['success' => 'success']);
        }
    
    Damien's avatar
    Damien committed
        public static function getUserInformationsById(array $args)
        {
            ValidatorModel::notEmpty($args, ['id']);
            ValidatorModel::intVal($args, ['id']);
    
    
    Florian Azizian's avatar
    Florian Azizian committed
            $user = UserModel::getById(['select' => ['id', 'login', 'email', 'firstname', 'lastname', 'picture', 'preferences'], 'id' => $args['id']]);
    
    Damien's avatar
    Damien committed
    
            if (empty($user['picture'])) {
                $user['picture'] = base64_encode(file_get_contents('src/frontend/assets/user_picture.png'));
                $user['picture'] = 'data:image/png;base64,' . $user['picture'];
            }
    
            $user['preferences'] = (array)json_decode($user['preferences']);
            $user['canManageRestUsers'] = UserController::hasPrivilege(['userId' => $args['id'], 'privilege' => 'manage_rest_users']);
    
            return $user;
        }
    
    
        public static function hasPrivilege(array $args)
    
        {
            ValidatorModel::notEmpty($args, ['userId', 'privilege']);
            ValidatorModel::intVal($args, ['userId']);
            ValidatorModel::stringType($args, ['privilege']);
    
            $groups = UserGroupModel::get(['select' => ['group_id'], 'where' => ['user_id = ?'], 'data' => [$args['userId']]]);
    
            foreach ($groups as $group) {
                $privilege = UserGroupModel::getPrivileges(['select' => [1], 'where' => ['group_id = ?', 'privilege = ?'], 'data' => [$group['group_id'], $args['privilege']]]);
                if (!empty($privilege)) {
                    return true;
                }
            }
    
            return false;
        }
    
    Florian Azizian's avatar
    Florian Azizian committed
    }