Commit 08fda3dc authored by Cyril Vazquez's avatar Cyril Vazquez
Browse files

Merge branch 'release/2.6.8' into 'Support/2.6.X'

Release/2.6.8

See merge request !598
parents ae2ff6f7 f6d95ace
Pipeline #10322 failed with stages
in 50 seconds
# CHANGELOG
## Version 2.6.8
- `Fixed` Versement des archives par batch
- `Fixed` Limitation des informations retournées et de la disponibilité du service de listage des comptes de service
- `Fixed` Gestion du caractère spécial * dans le nom de dossier virtuel.
## Version 2.6.7
- `Fixed` Gestion de l'affichage des ressources et pièces dans l'écran principal.
......@@ -54,7 +59,7 @@
### Sécurité
- `Fixed` Erreur courante `Attemp to access without a valid token` du module de protection CSRF, et traduction du message en français
- `Fixed` Impossibilité de rattacher un compte de service de niveau Administrateur Fonctionnel à une organisation (au lieu d'un service)
- `Fixed` Impossibilité de rattacher un compte de service de niveau Administrateur Fonctionnel à une organisation (au lieu d'un service)
- `Fixed` Faille XSS en faux positif sur la modale 404 "La page demandée n'existe pas"
- `Added` Gestion renforcée de la sécurité (option de configuration) : gestion de niveaux de sécurité sur les rôles et privilèges, en lien avec les niveaux d'utilisateur
- `Changed` Filtrage des comptes d'utilisateurs et comptes de service en fonction du niveau de sécurité, notamment pour le compte utilisé dans le planificateur de tâches (si activé)
......
2.6.7
\ No newline at end of file
2.6.8
......@@ -44,23 +44,23 @@ function symlink($target, $link)
* Improvements : the use of base conversion to get short ids with good entropy
* @param string $prefix A prefix for the generated id, if a specific class of characters is needed (XML ids must start with alpha)
* @param bool $moreEntropy Use more entropy
*
*
* @return string The unique id
*/
function uniqid($prefix = "", $moreEntropy = true)
{
$parts = \explode('.', microtime(true));
$sec = $parts[0];
if (!isset($parts[1])) {
$parts = \explode(' ', microtime());
$sec = $parts[1];
if (!isset($parts[0])) {
$msec = 0;
} else {
$msec = $parts[1];
$msec = substr($parts[0], 2, 6);
}
$uniqid = str_pad(base_convert($sec, 10, 36), 6, '0', STR_PAD_LEFT) . '-' . str_pad(base_convert($msec, 10, 16), 4, '0', STR_PAD_LEFT);
$uniqid = str_pad(base_convert($sec, 10, 36), 6, '0', STR_PAD_LEFT) . '-' . str_pad(base_convert($msec, 10, 36), 4, '0', STR_PAD_LEFT);
if ($moreEntropy) {
$uniqid .= '-' . str_pad(base_convert(mt_rand(), 10, 36), 6, '0', STR_PAD_LEFT);
$uniqid .= '-' . str_pad(base_convert(mt_rand(), 10, 36), 6, '0', STR_PAD_LEFT);
}
return $prefix . $uniqid;
......
......@@ -437,10 +437,6 @@ servicePrivileges = "[
'serviceURI' : 'recordsManagement/archives/updateArchivesretentionrule',
'description' : 'Mise à jour de la durée d\'utilité administrative'
},
{
'serviceURI' : 'recordsManagement/archives/updateArchivesretentionrule',
'description' : 'Mise à jour de la durée d\'utilité administrative'
},
{
'serviceURI' : 'recordsManagement/archive/read_archiveId_Digitalresource_resId_Contents',
'description' : 'Récupérer directement le contenu d\'une ressource d\'archive'
......@@ -516,10 +512,6 @@ servicePrivileges = "[
; 'description' : 'Purge des bordereaux'
; },
; {
; 'serviceURI' : 'recordsManagement/archives/updateArchivesretentionrule',
; 'description' : 'Mise à jour de la durée d\'utilité administrative'
; },
; {
; 'serviceURI': '*',
; 'description' : 'Tous les droits'
; }
......
......@@ -15,6 +15,7 @@ protected $page; // current page number
protected $n; // current object number
protected $offsets; // array of object offsets
protected $buffer; // buffer holding in-memory PDF
protected $fp; // buffer holding in-memory PDF
protected $pages; // array containing pages
protected $state; // current document state
protected $compress; // compression flag
......@@ -79,7 +80,8 @@ function __construct($orientation='P', $unit='mm', $size='A4')
$this->state = 0;
$this->page = 0;
$this->n = 2;
$this->buffer = '';
//$this->buffer = '';
$this->buffer = fopen('php://temp', 'w+');
$this->pages = array();
$this->PageInfo = array();
$this->fonts = array();
......@@ -999,6 +1001,7 @@ function Output($dest='', $name='', $isUTF8=false)
$dest = 'I';
if($name=='')
$name = 'doc.pdf';
rewind($this->buffer);
switch(strtoupper($dest))
{
case 'I':
......@@ -1012,7 +1015,8 @@ function Output($dest='', $name='', $isUTF8=false)
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: public');
}
echo $this->buffer;
//echo $this->buffer;
echo stream_get_contents($this->buffer);
break;
case 'D':
// Download file
......@@ -1021,16 +1025,23 @@ function Output($dest='', $name='', $isUTF8=false)
header('Content-Disposition: attachment; '.$this->_httpencode('filename',$name,$isUTF8));
header('Cache-Control: private, max-age=0, must-revalidate');
header('Pragma: public');
echo $this->buffer;
//echo $this->buffer;
echo stream_get_contents($this->buffer);
break;
case 'F':
// Save to local file
if(!file_put_contents($name,$this->buffer))
//if(!file_put_contents($name, $this->buffer))
// $this->Error('Unable to create output file: '.$name);
$fp = fopen($name, 'w');
if(!stream_copy_to_stream($this->buffer, $fp))
$this->Error('Unable to create output file: '.$name);
fclose($fp);
break;
case 'S':
// Return as a string
return $this->buffer;
//return $this->buffer;
return stream_get_contents($this->buffer);
default:
$this->Error('Incorrect output destination: '.$dest);
}
......@@ -1461,12 +1472,14 @@ public function _out($s)
protected function _put($s)
{
$this->buffer .= $s."\n";
//$this->buffer .= $s."\n";
fwrite($this->buffer, $s."\n");
}
protected function _getoffset()
{
return strlen($this->buffer);
//return strlen($this->buffer);
return ftell($this->buffer);
}
protected function _newobj($n=null)
......
......@@ -139,9 +139,11 @@ class Fpdi extends FpdfTpl
protected function _put($s, $newLine = true)
{
if ($newLine) {
$this->buffer .= $s . "\n";
//$this->buffer .= $s . "\n";
fwrite($this->buffer, $s . "\n");
} else {
$this->buffer .= $s;
//$this->buffer .= $s;
fwrite($this->buffer, $s);
}
}
}
......@@ -163,11 +163,21 @@ class StreamReader
*/
public function getBuffer($atOffset = true)
{
$end = ftell($this->buffer);
if (false === $atOffset) {
return $this->buffer;
//return $this->buffer;
rewind($this->buffer);
$string = stream_get_contents($this->buffer);
fseek($this->buffer, $end);
return (string) $string;
}
$string = substr($this->buffer, $this->offset);
//$string = substr($this->buffer, $this->offset);
fseek($this->buffer, $this->offset);
$string = stream_get_contents($this->buffer);
fseek($this->buffer, $end);
return (string) $string;
}
......@@ -191,7 +201,13 @@ class StreamReader
return false;
}
return $this->buffer[$position];
//return $this->buffer[$position];
$end = ftell($this->buffer);
fseek($this->buffer, $position);
$byte = fread($this->buffer, 1);
fseek($this->buffer, $end);
return $byte;
}
/**
......@@ -226,7 +242,13 @@ class StreamReader
}
$this->offset = $offset + 1;
return $this->buffer[$offset];
//return $byte;
$end = ftell($this->buffer);
fseek($this->buffer, $offset);
$byte = fread($this->buffer, 1);
fseek($this->buffer, $end);
return $byte;
}
/**
......@@ -261,7 +283,12 @@ class StreamReader
return false;
}
$bytes = substr($this->buffer, $offset, $length);
//$bytes = substr($this->buffer, $offset, $length);
$end = ftell($this->buffer);
fseek($this->buffer, $offset);
$bytes = fread($this->buffer, $length);
fseek($this->buffer, $end);
$this->offset = $offset + $length;
return $bytes;
......@@ -403,8 +430,14 @@ class StreamReader
fseek($this->stream, $pos);
$this->position = $pos;
$this->buffer = $length > 0 ? fread($this->stream, $length) : '';
$this->bufferLength = strlen($this->buffer);
//$this->buffer = $length > 0 ? fread($this->stream, $length) : '';
//$this->bufferLength = strlen($this->buffer);
$this->buffer = fopen('php://temp', 'w+');
if ($length > 0) {
$string = fread($this->stream, $length);
$this->bufferLength = fwrite($this->buffer, $string);
}
$this->offset = 0;
// If a stream wrapper is in use it is possible that
......@@ -412,8 +445,12 @@ class StreamReader
// increaseLength()-method to correct that behavior
if ($this->bufferLength < $length && $this->increaseLength($length - $this->bufferLength)) {
// increaseLength parameter is $minLength, so cut to have only the required bytes in the buffer
$this->buffer = substr($this->buffer, 0, $length);
$this->bufferLength = strlen($this->buffer);
//$this->buffer = substr($this->buffer, 0, $length);
//$this->bufferLength = strlen($this->buffer);
$newBuffer = fopen('php://temp', 'w+');
stream_copy_to_stream($this->buffer, $newBuffer, $length);
$this->buffer = $newBuffer;
$this->bufferLength = $length;
}
}
......@@ -452,8 +489,10 @@ class StreamReader
$newLength = $this->bufferLength + $length;
do {
$this->buffer .= fread($this->stream, $newLength - $this->bufferLength);
$this->bufferLength = strlen($this->buffer);
//$this->buffer .= fread($this->stream, $newLength - $this->bufferLength);
$addedLength = fwrite($this->buffer, fread($this->stream, $newLength - $this->bufferLength));
//$this->bufferLength = strlen($this->buffer);
$this->bufferLength += $addedLength;
} while (($this->bufferLength !== $newLength) && !feof($this->stream));
return true;
......
......@@ -25,10 +25,10 @@ class Statement
\IteratorAggregate
{
/* Constants */
/* Properties */
/* Properties */
protected $pdoStatement;
/* Methods */
/**
* Constructor
......@@ -38,7 +38,7 @@ class Statement
{
$this->pdoStatement = $pdoStatement;
}
/* Statement methods */
/**
* Bind a parameter
......@@ -48,7 +48,7 @@ class Statement
* @param integer $length
* @param array $driver_options
* @param string $ref
*
*
* @return bool
*/
public function bindParam($name, &$variable, $type=\PDO::PARAM_STR, $length=null, $driver_options=array(), $ref=false)
......@@ -58,45 +58,45 @@ class Statement
return $this->pdoStatement->bindParam(':' . $name, $variable, $type, $length);
}
/**
* Bind a value
* @param string $name
* @param string $value
* @param string $type
*
*
* @return bool
*/
public function bindValue($name, $value, $type=\PDO::PARAM_STR)
{
$this->params[$name] = $value;
return $this->pdoStatement->bindValue(':' . $name, $value, $type);
}
/**
* Return error
*
*
* @return \core\Error
*/
public function getError()
{
$errInfo = $this->pdoStatement->errorInfo();
return new \core\Error($errInfo[2], null, $errInfo[0], null, null, $errInfo);
}
/**
* execute
* @param string $inputParameters
*
*
* @return bool
*/
public function execute($inputParameters=null)
{
if (!empty($inputParameters) && \laabs\is_assoc($inputParameters)) {
foreach ($inputParameters as $name => $value) {
$inputParameters[":" . $name] = str_replace("*", "%", $value);
$inputParameters[":" . $name] = $value;
unset($inputParameters[$name]);
}
} else {
......@@ -105,7 +105,7 @@ class Statement
return $this->pdoStatement->execute($inputParameters);
}
/**
* Get params
* @return string
......@@ -114,7 +114,7 @@ class Statement
{
return $this->params;
}
/**
* Debug params
* @return string
......@@ -126,10 +126,10 @@ class Statement
/**
* ResultSet methods
*
*
* @param string $class
* @param array $ctor_args
*
*
* @return object
*/
public function fetch($class="\stdClass", array $ctor_args=array())
......@@ -143,16 +143,16 @@ class Statement
}
}
}
return $object;
}
/**
* ResultSet all methods
*
*
* @param string $class
* @param array $ctor_args
*
*
* @return object
*/
public function fetchAll($class="\stdClass", array $ctor_args=array())
......@@ -171,61 +171,61 @@ class Statement
return $resultSet;
}
/**
* Fetch item
* @param integer $cursor_offset
* @param string $class
*
*
* @return string
*/
public function fetchItem($cursor_offset=0, $class="\stdClass")
{
$this->setFetchMode(\PDO::FETCH_CLASS, $class);
return $this->pdoStatement->fetch(\PDO::FETCH_CLASS, \PDO::FETCH_ORI_ABS, $cursor_offset);
}
/**
* Fetch column
* @param integer $offset
*
*
* @return string
*/
public function fetchColumn($offset=0)
{
return $this->pdoStatement->fetchColumn($offset);
}
/**
* Row count
*
*
* @return integer
*/
public function rowCount()
{
return $this->pdoStatement->rowCount();
}
/**
* Get query string
*
*
* @return string
*/
public function getQueryString()
{
return $this->pdoStatement->queryString;
}
/**
* Get iterator
*
*
* @return \dependency\datasource\Adapter\Database\ArrayIterator
*/
public function getIterator()
{
$DataSet = $this->fetchAll();
return new ArrayIterator($DataSet);
}
......@@ -233,4 +233,4 @@ class Statement
{
return array();
}
}
\ No newline at end of file
}
......@@ -67,15 +67,28 @@ class serviceAccount
*/
public function index($limit = null)
{
return $this->sdoFactory->find('auth/account', "accountType='service'", null, null, null, $limit);
$serviceAccounts = $this->sdoFactory->find('auth/account', "accountType='service'", null, null, null, $limit);
$serviceAccounts = \laabs::castMessageCollection($serviceAccounts, 'auth/serviceAccountIndex');
return $serviceAccounts;
}
/**
* List all service to display
*
* @param string $accountName Name of account
* @param integer $maxResults Max result number to return
*
* @return array The array of stdClass with dislpay name and service identifier
*/
public function search()
public function search($accountName = null, $maxResults = null)
{
$serviceAccounts = $this->sdoFactory->find('auth/account', $this->getSearchQuery($accountName), null, false, false, $maxResults);
return $serviceAccounts;
}
public function getSearchQuery($accountName = null)
{
$accountId = \laabs::getToken("AUTH")->accountId;
$account = $this->sdoFactory->read("auth/account", array("accountId" => $accountId));
......@@ -85,6 +98,10 @@ class serviceAccount
$queryAssert = [];
$queryAssert[] = "accountType='service'";
if (!is_null($accountName) && $accountName != "null") {
$queryAssert[] = "accountName~'*$accountName*'";
}
if ($this->hasSecurityLevel) {
switch ($account->getSecurityLevel()) {
case $account::SECLEVEL_GENADMIN:
......@@ -112,9 +129,14 @@ class serviceAccount
}
}
$serviceAccounts = $this->sdoFactory->find('auth/account', \laabs\implode(" AND ", $queryAssert));
return \laabs\implode(" AND ", $queryAssert);
}
return $serviceAccounts;
public function searchCount($accountName = null)
{
$count = $this->sdoFactory->count('auth/account', $this->getSearchQuery($accountName));
return $count;
}
/**
......@@ -214,14 +236,14 @@ class serviceAccount
}
if ($this->hasSecurityLevel) {
if ($account->getSecurityLevel() == $account::SECLEVEL_FUNCADMIN && array_search($organization->orgName, array_column($this->organizationController->readDescendantServices($account->ownerOrgId), 'orgName')) === false){
if ($account->getSecurityLevel() == $account::SECLEVEL_FUNCADMIN && array_search($account->ownerOrgId, array_column($this->organizationController->readParentOrg($orgId), 'orgId')) === false){
throw new \core\Exception\ForbiddenException("You are not allowed to add user in this organization");
}
$this->checkPrivilegesAccess($account, $serviceAccount);
}
if (!$serviceAccount->ownerOrgId && !empty($orgId)) {
if(!empty($serviceAccount->ownerOrgId) && $serviceAccount->ownerOrgId != $organization->ownerOrgId) {
if (!empty($serviceAccount->ownerOrgId) && $serviceAccount->ownerOrgId != $organization->ownerOrgId) {
throw new \core\Exception\NotFoundException("Organization identified by " . $serviceAccount->ownerOrgId . " is not the owner organization of the organization identified by " . $orgId);
}
$serviceAccount->ownerOrgId = $organization->ownerOrgId;
......@@ -412,7 +434,10 @@ class serviceAccount
$ownAccount = $this->read($accountToken->accountId);
if ($accountToken->accountId != $serviceAccountId && $this->hasSecurityLevel) {
if (array_search($serviceAccount->accountName, array_column($this->search(), 'accountName')) === false){
$organization = $this->sdoFactory->read('organization/organization', $serviceAccount->ownerOrgId);
$organizations = $this->organizationController->readDescendantOrg($organization->orgId);
$organizations[] = $organization;
if (array_search($serviceAccount->ownerOrgId, array_column($organizations, 'orgId')) === false){
throw new \core\Exception\ForbiddenException("You are not allowed to modify this service account");
}
$this->checkPrivilegesAccess($ownAccount, $serviceAccount);
......@@ -478,6 +503,56 @@ class serviceAccount
return $this->sdoFactory->find("auth/servicePrivilege", "accountId='".$serviceAccountId."'");
}
/**
* Search accounts for a privilege
*
* @param string $serviceUri Privilege service uri
*
* @return array $accounts Array of service accounts with same privilege
*/
public function getAccountsByPrivilege($serviceUri)
{
$queryAssert = null;
if ($this->hasSecurityLevel) {
$accountId = \laabs::getToken("AUTH")->accountId;
$account = $this->sdoFactory->read("auth/account", array("accountId" => $accountId));
switch ($account->getSecurityLevel()) {
case $account::SECLEVEL_GENADMIN:
$queryAssert = " AND (isAdmin='TRUE' AND ownerOrgId!=null)";
break;
case $account::SECLEVEL_FUNCADMIN:
$organization = $this->sdoFactory->read('organization/organization', $account->ownerOrgId);