Newer
Older
<?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;
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;
use User\models\UserModel;
class UserController
{
public function get(Request $request, Response $response)
{
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'];
'select' => ['id', 'login', 'firstname', 'lastname', 'email'],
]);
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']);
$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']);
$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']);
} elseif (empty($body['email']) || !filter_var($body['email'], FILTER_VALIDATE_EMAIL)) {
return $response->withStatus(400)->withJson(['errors' => 'Body email is empty or not a valid email']);
$existingUser = UserModel::getByLogin(['login' => $body['login'], 'select' => [1]]);
return $response->withStatus(400)->withJson(['errors' => 'Login already exists']);
}
$logingModes = ['standard', 'rest'];
if (empty($body['mode']) || !in_array($body['mode'], $logingModes)) {
$body['mode'] = 'standard';
$body['picture'] = empty($body['picture']) ? null : $body['picture'];
'code' => 'OK',
'objectType' => 'users',
'objectId' => $id,
'type' => 'CREATION',
'message' => "User added : {$body['firstname']} {$body['lastname']}"
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']);
$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']);
}
$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']);
if (!$check) {
return $response->withStatus(400)->withJson(['errors' => 'Missing parameter in user preferences data']);
}
$body['preferences'] = json_encode($body['preferences']);
if (!is_string($body['preferences'])) {
return $response->withStatus(400)->withJson(['errors' => 'Wrong format for user preferences data']);
}
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);
$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']);
}
$imagick->readImageBlob(base64_decode($body['picture']));
$imagick->rotateImage(new \ImagickPixel(), $body['pictureOrientation']);
$body['picture'] = base64_encode($imagick->getImageBlob());
'firstname' => $body['firstname'],
'lastname' => $body['lastname'],
'preferences' => $body['preferences']
if (!empty($body['picture'])) {
$set['picture'] = $body['picture'];
}
UserModel::update([
'set' => $set,
'where' => ['id = ?'],
'data' => [$args['id']]
]);
'code' => 'OK',
'objectType' => 'users',
'objectId' => $args['id'],
'type' => 'MODIFICATION',
'message' => "User updated : {$body['firstname']} {$body['lastname']}"
return $response->withJson(['user' => UserController::getUserInformationsById(['id' => $args['id']])]);
}
public function updatePassword(Request $request, Response $response, array $args)
{
$data = $request->getParams();
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']]);
}
'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)
if ($GLOBALS['id'] != $args['id'] && !UserController::hasPrivilege(['userId' => $GLOBALS['id'], 'privilege' => 'manage_users'])) {
return $response->withStatus(403)->withJson(['errors' => 'Privilege forbidden']);
$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([
'select' => ['id', 'path', 'filename', 'fingerprint'],
'where' => ['user_id = ?'],
'data' => [$args['id']],
'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[] = [
'id' => $signature['id'],
'encodedSignature' => base64_encode(file_get_contents($pathToSignature))
return $response->withJson(['signatures' => $signatures]);
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']);
}
$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']]);
}
'userId' => $args['id'],
'path' => $storeInfos['path'],
'filename' => $storeInfos['filename'],
'fingerprint' => $storeInfos['fingerprint'],
]);
'code' => 'OK',
'objectType' => 'signatures',
'objectId' => $id,
'type' => 'CREATION',
'message' => "Signature added",
return $response->withJson(['signatureId' => $id]);
}
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']);
}
UserModel::deleteSignature(['where' => ['user_id = ?', 'id = ?'], 'data' => [$args['id'], $args['signatureId']]]);
'code' => 'OK',
'objectType' => 'signatures',
'objectId' => $args['signatureId'],
'type' => 'SUPPRESSION',
'message' => "Signature deleted",
return $response->withJson(['success' => 'success']);
}
public static function getUserInformationsById(array $args)
{
ValidatorModel::notEmpty($args, ['id']);
ValidatorModel::intVal($args, ['id']);
$user = UserModel::getById(['select' => ['id', 'login', 'email', 'firstname', 'lastname', 'picture', 'preferences'], 'id' => $args['id']]);
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;
}