Commit 2a9d8f97 authored by Arnaud Pauget's avatar Arnaud Pauget
Browse files

Merge branch 'Support/2.8.X' into 'master'

Version 2.8

See merge request !700
parents cacb0b22 742171fd
Pipeline #15419 failed with stages
in 20 seconds
......@@ -5,6 +5,7 @@ data/maarchRM/luceneIndex/
data/maarchRM/conf/vhost.win.conf
data/maarchRM/conf/vhost.conf
web/tmp
data/tmp
web/public/dependency/
dependency/fileSystem/plugins/fid/cache/*
dependency/csrf/log/*
......
# CHANGELOG
## Version 2.8
- `Added` Connecteur de réception des paquets restitués depuis la plateforme T@ct de API.
- `Added` Possibilité pour les service producteurs d'indexer le contenu texte des documents archivés afin de pouvoir les rechercher sur l'intégralité des termes.
- `Added` Possibilité d'ajouter des critères supplémentaires lors d'une recherche dans l'écran de gestion.
- `Added` Possibilité pour les gestionnaires d'archive de regrouper les archives de leur choix dans une collection de favoris afin de simplifier les actions de gestion sur un ensemble d'archives.
- `Added` Nouveau point de menu pour accéder directement à sa collection de favoris.
- `Added` Possibilité de définir la date de référence pour le calcul de la date d'élimination d'un dossier en fonction de la date du dernier versement de pièce afin de prolonger la conservation des dossiers actifs.
- `Added` Possibilité d'activer la découverte d'un profil d'archive pour d'autre service que le producteur original (droit d'en connaître).
- `Added` Recherche des digitalResources par critères (via API uniquement).
- `Changed` Evolution des champs affichés dans les résultats de recherche de l'écran de gestion.
- `Fixed` Erreur au lancement de la tâche planifiée "Intégrité Périodique" par le compte Système.
- `Fixed` Possibilité de lister les contenus présents dans le répertoire public/web.
- `Fixed` Compatibilité timestamp pour version de postgres >= 12.
- `Fixed` Compatibilité PHP 8.0.
- `Fixed` Contrôle des droits de versement des archives dans profil conteneur lors d'un versement via bordereau MADES.
- `Fixed` Retrait du bouton de modification des métadonnées d'archive MADES.
- `Fixed` Vérifier la communicabilité des pièces d'archives (sous archive) lors d'une demande de communication.
- `Added` Possibilité de configurer un lien avec serveur AD pour authentification via Kerberos.
- `Fixed` Détection de format puid lors d'un versement MADES.
- `Fixed` Demande de communication sur plusieurs archives.
- `Fixed` Recherche par côte d'archive (archiver identifier).
- `Fixed` Non affichage de la liste des règles de conservation dans l'écran de registre
- `Fixed` Affichage des dates extrêmes
- `Fixed` Impossibilité de traduire l'exception auth\UknownUserException
- `Fixed` Affichage des journaux archivés
- `Changed` Changement du bouton de visualisation d'une ressource en téléchargement direct de la ressource afin d'éviter la lecture par le navigateur.
- `Changed` Comportement de la directive archivalProfileType 1 identique désormais à la 3
## Version 2.7.4
- `Fixed` Mauvaise ventilation par profil d'archive et service producteur dans l'onglet statistique
- `Fixed` Impossibilité de sauvegarder des métadonnées de type datetime via l'écran
......
# Migration 2.7 vers 2.8
## Vhost :
### Ajout du bundle 'collection'
Afin d'accéder aux fonctionnalités relatives aux collections, le bundle `Collection` doit être ajoutée à l'instance dans le fichier vhost.conf :
```
SetEnv LAABS_BUNDLES audit;auth;batchProcessing;contact;digitalResource;lifeCycle;organization;recordsManagement;filePlan;medona;mades;digitalSafe;Statistics;Collection
```
### Blocage de l'accès au répertoire 'web/public' dans l'URL
Modifications vhost. Retrait de la condition Rewrite. Remplacer :
```
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_URI} ^/public [NC]
```
Par :
```
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -f
```
### Ajout d'un exemple de configuration pour la vérification d'authentification via Kerberos.
## Modification dans la configuration :
### Ajout
Dans la section [recordsManagement], ajout de la directive `actionWithoutCommunicationRule` qui permet de définir le comportement de l'application si une archive ne possède pas de règle de communication. `deny` = ne pas autoriser la demande de communication, `allow` = autoriser la demande de communication.
Dans la section [lifeCycle], ajout de la directive `notifications` qui permet de paramétrer des notifications email en se branchant sur les évènements du cycle de vie de l'application.
Dans la section [dependency.fileSystem], ajout de la directive `fullTextServices` qui permet de paramétrer les services qui effectueront l'extraction FullText.
Dans la section [dependency.fileSystem], ajout des directives `tikaJarExecutable` et `tesseractExecutable` qui sont 2 exemples de services permettant l'extraction de texte à partir d'un document ou d'une image.
### Modification
Mise à jour de la route de service dans [auth] -> 'servicePrivileges' pour le contrôle d'intégrité qui n'aboutissait pas car la casse était mauvaise.
Dans la section [dependency.sdo], modification de la directive `datetimeFormat` pour respecter le format de date iso 8601.
Dans la section [batchProcessing], ajout d'une tâche dans la directive `tasks` qui permet d'ajouter la tâche planifiée qui exécute l'extraction FullText.
## Menu
### Point de menu Collection / Favoris
Un point de menu a été ajouté pour accéder directement à la vue de ses archives favorites :
`menu` :
```
{
'label' : '',
'title' : 'Favoris',
'href' : '/collection',
'class' : 'fa fa-star fa-fw'
}
```
## Schéma SQL
Voir le fichier spécifique
laabs/data/maarchRM/sql/pgsql/migrationV2.7_V2.8.sql
# Migration 2.6 vers 2.7
## Configuration
## Ajout dans la configuration
Dans la section [recordsManagement], ajout dee la directive `archiveIdGenerator` qui permet de configurer la cotation automatique lors d'un versement dans l'application.
Dans la section [recordsManagement], ajout de la directive `archiveIdGenerator` qui permet de configurer la cotation automatique lors d'un versement dans l'application.
Dans la section [medona], ajout de la directive `packageConnectors` qui permet la configuration de connecteurs pour faciliter le versement de paquets externes au format incomplet.
......@@ -126,9 +189,9 @@ Voir le fichier spécifique
# Migration 2.5 vers 2.6
## Configuration
### Lien de téléchargement d'une ressource
Cette configuration facultative permet au moment de la consultation, de recevoir une uri vers une ressource au lieu du contenu binaire.
Cette configuration facultative permet au moment de la consultation, de recevoir une uri vers une ressource au lieu du contenu binaire.
À renseigner dans [recordsManagement] :
À renseigner dans [recordsManagement] :
```
exportPath = "%laabsDirectory%/web/tmp"
```
......@@ -136,8 +199,8 @@ exportPath = "%laabsDirectory%/web/tmp"
## Configuration des instances publiées (hôte(s) virtuel(s) http et scripts en ligne de commande)
### Externalisation du bundle `digitalSafe`
Le bundle `digitalSafe` qui présente les fonctions relatives à l'usage du produit
comme composant de coffre-fort numérique, ajouté en V2.5, a été déplacé dans une nouvelle
Le bundle `digitalSafe` qui présente les fonctions relatives à l'usage du produit
comme composant de coffre-fort numérique, ajouté en V2.5, a été déplacé dans une nouvelle
extension du même nom.
Les instances ne doivent plus faire référence à ce bundle si l'extension `digitalSafe` n'est pas installée.
......@@ -154,14 +217,14 @@ SetEnv LAABS_EXTENSIONS digitalSafe
```
### Nouvelle dépendance technique CSV
Les fonctions d'import et d'export de référentiel utilisent une nouvelle dépendance qui
Les fonctions d'import et d'export de référentiel utilisent une nouvelle dépendance qui
gère les conversions en CSV. Ladépendance `csv` doit être ajoutée à l'instance :
```
SetEnv LAABS_DEPENDENCIES repository;xml;html;localisation;datasource;sdo;json;fileSystem;notification;PDF;csrf;timestamp;csv
```
## Configuration
## Configuration
### Protection CSRF
Il faut ajouter des routes en liste blanche pour la protection contre les requêtes en Cross-Site Forgery:
......
{
"require-dev": {
"codeception/codeception": "^3.0",
"flow/jsonpath" : "^0.4"
"flow/jsonpath" : "^0.4",
"phpcompatibility/php-compatibility": "*"
},
"prefer-stable" : true,
"scripts": {
"post-install-cmd": "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility",
"post-update-cmd" : "\"vendor/bin/phpcs\" --config-set installed_paths vendor/phpcompatibility/php-compatibility"
}
}
......@@ -379,7 +379,7 @@ class PresentationKernel
}
$presenterArgs = array_merge($presenterArgs, $this->userMessage);
$content = $this->viewRouter->view->present($presenter, $presenterArgs);
$content = $this->viewRouter->view->present($presenter, array_values($presenterArgs));
} else {
......
......@@ -297,7 +297,7 @@ class ServiceKernel extends AbstractKernel
}
$controller = $this->actionRouter->controller->newInstance();
$this->actionReturn = $this->actionRouter->action->call($controller, $this->actionArguments);
$this->actionReturn = $this->actionRouter->action->call($controller, array_values($this->actionArguments));
//$serviceReturnType = $this->serviceRoute->getReturnType();
//$this->serviceReturn = \laabs::castMessage($this->actionReturn, $serviceReturnType);
......
......@@ -7,7 +7,7 @@ class ComparisonOperation
extends AbstractBinaryOperation
{
public function __construct($code=LAABS_T_EQUAL, $left, $right=LAABS_T_TRUE)
public function __construct($code=LAABS_T_EQUAL, $left=null, $right=LAABS_T_TRUE)
{
parent::__construct($code, $left, $right);
}
......
......@@ -7,7 +7,7 @@ class LogicalOperation
extends AbstractBinaryOperation
{
public function __construct($code=LAABS_T_AND, $left, $right)
public function __construct($code = LAABS_T_AND, $left = null, $right = null)
{
parent::__construct($code, $left, $right);
}
......
......@@ -602,13 +602,13 @@ class Bundle
/**
* Instantiate a new exception object from bundle exception component
* @param string $name The name of the exception to instantiate
* @param string $nameUri The name of the exception to instantiate
*
* @return object
*/
public function newException($name)
public function newException($nameUri)
{
$exception = $this->getException($name);
$exception = $this->getException($nameUri);
$args = func_get_args();
array_shift($args);
......
......@@ -69,7 +69,7 @@ class Message
*
* @return object The new object
*/
public function newInstance($passedArgs=array())
public function newInstance($passedArgs = null, ...$args)
{
// Get construction method
if ($constructor = $this->getConstructor()) {
......
......@@ -4,13 +4,13 @@
* @package core\Reflection
*/
namespace core\Reflection;
/**
* Class that defines a service or method parameter
*
*
* @uses \core\ReadonlyTrait
*/
class Parameter
extends \ReflectionParameter
class Parameter extends \ReflectionParameter
{
/* Properties */
/**
......@@ -21,7 +21,7 @@ class Parameter
/**
* @var string The documentation
*/
public $description;
public $description;
/* Methods */
/**
......@@ -30,28 +30,31 @@ class Parameter
* @param string $method The name of the method
* @param string $class The class of the service that declares the method
* @param string $type The type of parameter retrieved from method doc comments
* @param string $doc The documentation retrieved from method doc comments
* @param string $doc The documentation retrieved from method doc comments
*/
public function __construct($name, $method, $class, $type=null, $doc=false)
public function __construct($name, $method, $class, $type = null, $doc = false)
{
parent::__construct(array($class, $method), $name);
$this->description = $doc;
$this->type = $type;
if (version_compare(PHP_VERSION, '8.0.0', '>=') && parent::getType()) {
$this->type = parent::getType()->getName();
} else {
$this->type = $type;
// Unknown array type
if ($this->isArray() && !$type) {
$this->type = 'array';
}
// Unknown array type
if (parent::getType() && parent::getType()->getName() === 'array' && !$type) {
$this->type = 'array';
}
// Class
if (preg_match('/\\[\s\<\w+?>\s([\w\\\\]+)/s', $this->__toString(), $matches)) {
if (isset($matches[1])) {
$this->type = $matches[1];
}
// Class
if (preg_match('/\\[\s\<\w+?>\s([\w\\\\]+)/s', $this->__toString(), $matches)) {
if (isset($matches[1])) {
$this->type = $matches[1];
}
}
}
}
/**
......@@ -62,5 +65,4 @@ class Parameter
{
return $this->type;
}
}
......@@ -208,7 +208,11 @@ class Property
break;
case 'enumeration':
@eval('$enumeration = '.trim($tagvalues[0]).';');
try {
@eval('$enumeration = '.trim($tagvalues[0]).';');
} catch (\Error $e) {
$enumeration = \laabs\explode(',', substr(trim($tagvalues[0]), 1, -1));
}
$this->enumeration = $enumeration;
break;
......@@ -217,11 +221,11 @@ class Property
break;
case 'scale':
$this->scale = (int) $tagvalues[0];
$this->scale = (int) ($tagvalues)[0];
break;
case 'minvalue':
$this->minValue = (int) $$tagvalues[0];
$this->minValue = (int) $tagvalues[0];
break;
case 'maxvalue':
......
......@@ -166,24 +166,21 @@ class Service
*
* @return object The service object
*/
public function newInstance($passedArgs=array())
public function newInstance($passedArgs = null, ...$args)
{
// Get construction method
if ($this->hasConstructor()) {
$constructor = $this->getConstructor();
$constructorArgs = $constructor->getCallArgs($passedArgs, $this->configuration);
$serviceObject = parent::newInstanceArgs($constructorArgs);
$serviceObject = parent::newInstanceArgs($constructorArgs);
} elseif ($this->hasMethod($this->getShortName()) && ($method = $this->getMethod($this->getShortName())) && $method->isStatic() && $method->isPublic()) {
$staticFactory = $this->getMethod($this->getShortName());
$staticFactoryArgs = $staticFactory->getCallArgs($passedArgs, $this->configuration);
$serviceObject = $staticFactory->callArgs(null, $staticFactoryArgs);
} else {
$serviceObject = parent::newInstanceWithoutConstructor();
}
$this->useTraits($serviceObject, $passedArgs);
......
<?php
namespace core\Reflection;
/**
* Class for trait/data type definitions
*
* @extends \core\Reflection\Service
*/
class Trait
extends Service
{
/* Constants */
/* Properties */
/**
* @var string
*/
public $extension;
/* Methods */
/**
* Constructor of the injection service
* @param string $uri The uri of the service
* @param string $class The class of the service
* @param object $container The service container object
*/
public function __construct($uri, $class, $container)
{
parent::__construct($uri, $class, $container);
}
/**
* Parse self and parent class doc comment recursively
*/
protected function parseDocComment()
{
if ($parentClass = $this->getParentClass()) {
$this->importDocComments($parentClass->getName());
$this->extension = \laabs::getClassName($parentClass->name);
}
}
protected function importDocComments($className)
{
$traitName = \laabs::getClassName($className);
$type = \laabs::getClass($traitName);
}
/**
* Get the parent type name
* @return string
*/
public function getExtensionName()
{
return $this->extension;
}
/**
* Get the schema (bundle)
* @return \core\Reflection\bundle
*/
public function getSchema()
{
return $this->container;
}
/**
* Get a property definition
* @param string $name The name of the property to get
*
* @return \core\Reflection\Property The property definition object
*/
public function getProperty($name)
{
$rProperty = parent::getProperty($name);
return new Property($rProperty->name, $this->name, $this);
}
/**
* Get all property definitions
* @param int $filter A bitmask of property modifiers
*
* @return array of \core\Reflection\Property The property definition objects
*/
public function getProperties($filter=null)
{
$properties = array();
foreach ((array) parent::getProperties() as $rProperty) {
$properties[] = new Property($rProperty->name, $this->name, $this);
}
return $properties;
}
}
......@@ -142,22 +142,43 @@ abstract class AbstractRequest
*/
protected function getAuthentication()
{
if (isset($_SERVER['PHP_AUTH_USER'])) {
$this->authentication = new basicAuthentication($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
} elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) {
$neededParts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
$data = array();
$keys = implode('|', array_keys($neededParts));
preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $_SERVER['PHP_AUTH_DIGEST'], $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$data[$match[1]] = $match[3] ? $match[3] : $match[4];
unset($neededParts[$match[1]]);
}
$this->authentication = $this->selectAuthentication();
}
$this->authentication = new digestAuthentication($data['username'], $data['nonce'], $data['uri'], $data['response'], $data['qop'], $data['nc'], $data['cnonce']);
}
protected function selectAuthentication()
{
$authModes = \laabs::getAuthModes();
foreach ($authModes as $authMode) {
switch ($authMode) {
case LAABS_BASIC_AUTH:
if (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
return new basicAuthentication($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
}
break;
case LAABS_DIGEST_AUTH:
if (isset($_SERVER['PHP_AUTH_DIGEST'])) {
$neededParts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
$data = array();
$keys = implode('|', array_keys($neededParts));
preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $_SERVER['PHP_AUTH_DIGEST'], $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$data[$match[1]] = $match[3] ? $match[3] : $match[4];
unset($neededParts[$match[1]]);
}
return new digestAuthentication($data['username'], $data['nonce'], $data['uri'], $data['response'], $data['qop'], $data['nc'], $data['cnonce']);
}
break;
case LAABS_REMOTE_AUTH:
if (isset($_SERVER['REMOTE_USER']) && isset($_SERVER['AUTH_TYPE'])) {
return new remoteAuthentication($_SERVER['REMOTE_USER'], $_SERVER['AUTH_TYPE']);
}
break;
}
}
}
}
\ No newline at end of file
<?php
namespace core\Request;
/**
* Class to represent app authentication
*/
class remoteAuthentication
extends abstractAuthentication
{
public static $mode = LAABS_REMOTE_AUTH;
public $remoteUser;
public $authType;
public function __construct($remoteUser, $authType)
{
$this->remoteUser = $remoteUser;
$this->authType = $authType;
}
}
\ No newline at end of file
......@@ -137,6 +137,7 @@ const LAABS_BATCH_STATUS_COMPLETED = "Completed";
const LAABS_BASIC_AUTH = "basic";
const LAABS_DIGEST_AUTH = "digest";
const LAABS_APP_AUTH = "app";
const LAABS_REMOTE_AUTH = "remote";
// TOKENS
// Operations
......
......@@ -524,13 +524,13 @@ trait laabsAppTrait
/**
* Instanciate a new exception. All additional arguments will be passed to constructor
* @param string $exceptionName The exception name bundle/exception
* @param string $exceptionUri The exception name bundle/exception
*
* @return Exception
*/
public static function newException($exceptionName)
public static function newException($exceptionUri)
{
$bundleName = strtok($exceptionName, LAABS_URI_SEPARATOR);
$bundleName = strtok($exceptionUri, LAABS_URI_SEPARATOR);
$exceptionName = strtok(LAABS_URI_SEPARATOR);
$constructorArgs = func_get_args();
......@@ -1392,4 +1392,14 @@ trait laabsAppTrait
}
/**
* Get the auth methods
*
* @return array
*/
public static function getAuthModes()
{
return self::getList('LAABS_AUTH_MODES');
}
}
......@@ -446,13 +446,13 @@ trait laabsModelTrait
/**
* Instanciate a new object with given type name
* @param string $className The class name bundle/class
* @param string $classUri The class name bundle/class
*
* @return object
*/
public static function newInstance($className)
public static function newInstance($classUri)
{
$bundleName = strtok($className, LAABS_URI_SEPARATOR);
$bundleName = strtok($classUri, LAABS_URI_SEPARATOR);
$className = strtok(LAABS_URI_SEPARATOR);
$type = self::bundle($bundleName)->getClass($className);
......