Verified Commit 29a7a083 authored by Alexis Ragot's avatar Alexis Ragot
Browse files

v2.2

parent fe232f3f
......@@ -119,12 +119,13 @@ class ArchiveTransfer extends \ext\demorm_publique\bundle\medona\Controller\abst
* Receive message with all contents embedded
* @param string $messageFile The message binary contents OR a filename
* @param array $attachments An array of attachment binary data
* @param string $filename The message file name
*
* @return medona/message
*
* @todo Remove files from sas when error on reception
*/
public function receive($messageFile, $attachments = array())
public function receive($messageFile, $attachments = array(), $filename = false)
{
$messageId = \laabs::newId();
$message = \laabs::newInstance('medona/message');
......@@ -132,6 +133,7 @@ class ArchiveTransfer extends \ext\demorm_publique\bundle\medona\Controller\abst
$message->type = "ArchiveTransfer";
$message->receptionDate = \laabs::newTimestamp();
$messageDir = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId;
if (!is_dir($messageDir)) {
mkdir($messageDir, 0777, true);
......@@ -153,7 +155,7 @@ class ArchiveTransfer extends \ext\demorm_publique\bundle\medona\Controller\abst
case 'application/zip':
case 'application/octet-stream':
$this->receiveZip($message, $messageFile);
$this->receiveZip($message, $messageFile, $filename);
break;
}
}
......@@ -163,6 +165,20 @@ class ArchiveTransfer extends \ext\demorm_publique\bundle\medona\Controller\abst
if ($message->schema != 'medona') {
$archiveTransferController = \laabs::newController($message->schema.'/ArchiveTransfer');
$archiveTransferController->receive($message);
$errors = $archiveTransferController->checkResources($message);
if ($errors) {
$messageURI = $this->messageDirectory.DIRECTORY_SEPARATOR.$message->messageId;
if (is_dir($messageURI)) {
\laabs\rmdir($messageURI, true);
}
$exception = \laabs::newException('medona/invalidMessageException', "Invalid message", $errors[0]->getCode());
$exception->errors = $errors;
throw $exception;
}
} else {
// Validate xsd
$schemaFile = LAABS_EXTENSION.DIRECTORY_SEPARATOR.'thirdPartyArchiving'.DIRECTORY_SEPARATOR.LAABS_BUNDLE.DIRECTORY_SEPARATOR.'medona'.DIRECTORY_SEPARATOR.LAABS_RESOURCE.DIRECTORY_SEPARATOR.'xml'.DIRECTORY_SEPARATOR.'medona_V1.0.xsd';
......@@ -235,6 +251,21 @@ class ArchiveTransfer extends \ext\demorm_publique\bundle\medona\Controller\abst
$message->size += (integer) $size;
}
}
$this->checkResources($message);
if ($this->errors) {
$messageURI = $this->messageDirectory.DIRECTORY_SEPARATOR.$message->messageId;
if (is_dir($messageURI)) {
\laabs\rmdir($messageURI, true);
}
$exception = \laabs::newException('medona/invalidMessageException', "Invalid message", $this->errors[0]->getCode());
$exception->errors = $this->errors;
throw $exception;
}
}
try {
......@@ -348,33 +379,44 @@ class ArchiveTransfer extends \ext\demorm_publique\bundle\medona\Controller\abst
}
}
protected function receiveZip($message, $zipstream)
protected function receiveZip($message, $zipstream, $filename)
{
$messageDir = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId;
$zipfile = \laabs\tempnam();
file_put_contents($zipfile, $zipstream);
$zip = \laabs::newService('dependency/fileSystem/plugins/zip');
$zip->extract($zipfile, $messageDir);
$zipContents = scandir($messageDir);
if (!isset($zipContents[2])) {
throw \laabs::newException('medona/invalidMessageException', "Invalid message", 400);
}
if (is_dir($messageDir.DIRECTORY_SEPARATOR.$zipContents[2])) {
$zipFolder = $messageDir.DIRECTORY_SEPARATOR.$zipContents[2];
foreach (scandir($zipFolder) as $file) {
if ($file != "." && $file != "..") {
rename($zipFolder.DIRECTORY_SEPARATOR.$file, $messageDir.DIRECTORY_SEPARATOR.$file);
}
}
var_dump($zipContents);
exit;
rmdir($zipFolder);
}
$filename = explode('.', $filename);
array_pop($filename);
$filename = implode('.', $filename);
$messageFile = file_get_contents($messageDir.DIRECTORY_SEPARATOR.$filename.'.xml');
// Load file xml
$this->loadXml($message, $messageFile);
// Save to message directory
$this->save($message);
if (count($attachments)) {
foreach ($attachments as $attachment) {
$attachment->data = base64_decode($attachment->data);
file_put_contents($messageDir.DIRECTORY_SEPARATOR.$attachment->filename, $attachment->data);
}
}
unlink($messageDir.DIRECTORY_SEPARATOR.$filename.'.xml');
}
/**
......@@ -886,20 +928,8 @@ class ArchiveTransfer extends \ext\demorm_publique\bundle\medona\Controller\abst
$archives = $message->object->dataObjectPackage->descriptiveMetadata->archive;
$binaryDataObjects = (array) $message->object->dataObjectPackage->binaryDataObject;
foreach ($archives as $archive) {
foreach ($archive->digitalResources as $digitalResource) {
if (!isset($binaryDataObjects[$digitalResource->resId])) {
$this->sendError("213", "Le document identifié par '$digitalResource->resId' est introuvable.");
}
}
}
$fromdir = dirname($message->xml->uri);
// List received files
$receivedFiles = glob($fromdir.DIRECTORY_SEPARATOR."*.*");
// List actual message files, starting with message xml itself
$messageFiles = array($message->xml->uri);
if (count($binaryDataObjects)) {
foreach ($binaryDataObjects as $dataObjectId => $binaryDataObject) {
......@@ -907,36 +937,15 @@ class ArchiveTransfer extends \ext\demorm_publique\bundle\medona\Controller\abst
if ($attachment->filename) {
$filepath = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId.DIRECTORY_SEPARATOR.$attachment->filename;
if (!is_file($filepath)) {
$this->sendError("211", "Le document identifié par le nom '$attachment->filename' n'a pas été trouvé.");
continue;
}
$contents = file_get_contents($filepath);
$messageFiles[] = $attachment->filename;
} elseif ($attachment->uri) {
$contents = file_get_contents($attachment->getAttribute('uri'));
if (!$contents) {
$this->sendError("211", "Le document à l'adresse '$attachment->uri' est indisponible.");
continue;
}
$filepath = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId.DIRECTORY_SEPARATOR.$dataObjectId;
file_put_contents($filepath, $contents);
} else {
if (strlen($attachmentElement->value) == 0) {
$this->sendError("211", "Le contenu du document n'a pas été transmis.");
continue;
}
$contents = base64_decode($attachment->value);
$filepath = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId.DIRECTORY_SEPARATOR.$dataObjectId;
file_put_contents($filepath, $contents);
}
......@@ -953,11 +962,6 @@ class ArchiveTransfer extends \ext\demorm_publique\bundle\medona\Controller\abst
} else {
$puid = $format->puid;
$fileInfo->format = $format;
/*if ($format->puid != $attachment->format) {
$this->sendError("205 Format de document non conforme au format déclaré.");
array_push($this->errors, new \core\Error("Le format du document '".basename($filepath)."' ".$format->puid." ne correspond pas à celui indiqué (".$attachment->format.")."));
}*/
}
}
......@@ -974,12 +978,6 @@ class ArchiveTransfer extends \ext\demorm_publique\bundle\medona\Controller\abst
}
}
// Validate hash
$messageDigest = $binaryDataObject->messageDigest;
if (strtolower($messageDigest->value) != strtolower(hash($messageDigest->algorithm, $contents))) {
$this->sendError("207", "L'empreinte numérique du document '".basename($filepath)."' ne correspond pas à celle transmise.");
}
if (($arr = get_object_vars($fileInfo)) && !empty($arr)) {
file_put_contents(
$this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId.DIRECTORY_SEPARATOR.$dataObjectId.'.info',
......@@ -988,15 +986,6 @@ class ArchiveTransfer extends \ext\demorm_publique\bundle\medona\Controller\abst
}
}
}
// Check all files received are part of the message
foreach ($receivedFiles as $receivedFile) {
if (!in_array(basename($receivedFile), $messageFiles) && basename($receivedFile) != basename($message->xml->uri)) {
$this->sendError("101", "Le fichier '".basename($receivedFile)."' ,'est pas référencé dans le bordereau.");
return;
}
}
}
protected function validateArchiveRelationships($descriptiveMetadata)
......@@ -1018,6 +1007,80 @@ class ArchiveTransfer extends \ext\demorm_publique\bundle\medona\Controller\abst
return;
}
public function checkResources($message) {
$archives = $message->object->dataObjectPackage->descriptiveMetadata->archive;
$binaryDataObjects = (array) $message->object->dataObjectPackage->binaryDataObject;
foreach ($archives as $archive) {
foreach ($archive->digitalResources as $digitalResource) {
if (!isset($binaryDataObjects[$digitalResource->resId])) {
$this->sendError("213", "Le document identifié par '$digitalResource->resId' est introuvable.");
}
}
}
$fromdir = dirname($message->xml->uri);
// List received files
$receivedFiles = glob($fromdir.DIRECTORY_SEPARATOR."*.*");
// List actual message files, starting with message xml itself
$messageFiles = array($message->xml->uri);
if (count($binaryDataObjects)) {
foreach ($binaryDataObjects as $dataObjectId => $binaryDataObject) {
$attachment = $binaryDataObject->attachment;
if ($attachment->filename) {
$filepath = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId.DIRECTORY_SEPARATOR.$attachment->filename;
if (!is_file($filepath)) {
$this->sendError("211", "Le document identifié par le nom '$attachment->filename' n'a pas été trouvé.");
continue;
}
$contents = file_get_contents($filepath);
$messageFiles[] = $attachment->filename;
} elseif ($attachment->uri) {
$contents = file_get_contents($attachment->getAttribute('uri'));
if (!$contents) {
$this->sendError("211", "Le document à l'adresse '$attachment->uri' est indisponible.");
continue;
}
$filepath = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId.DIRECTORY_SEPARATOR.$dataObjectId;
} else {
if (strlen($attachmentElement->value) == 0) {
$this->sendError("211", "Le contenu du document n'a pas été transmis.");
continue;
}
$contents = base64_decode($attachment->value);
$filepath = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId.DIRECTORY_SEPARATOR.$dataObjectId;
}
// Validate hash
$messageDigest = $binaryDataObject->messageDigest;
if (strtolower($messageDigest->value) != strtolower(hash($messageDigest->algorithm, $contents))) {
$this->sendError("207", "L'empreinte numérique du document '".basename($filepath)."' ne correspond pas à celle transmise.");
}
}
}
// Check all files received are part of the message
foreach ($receivedFiles as $receivedFile) {
if (!in_array(basename($receivedFile), $messageFiles) && basename($receivedFile) != basename($message->xml->uri)) {
$this->sendError("101", "Le fichier '".basename($receivedFile)."' ,'est pas référencé dans le bordereau.");
return;
}
}
}
/**
* Process the messages
*
......@@ -1039,6 +1102,9 @@ class ArchiveTransfer extends \ext\demorm_publique\bundle\medona\Controller\abst
}
}
$logMessage = ["message" => "%s message(s) processed", "variables"=> count($results)];
\laabs::notify(\bundle\audit\AUDIT_ENTRY_OUTPUT, $logMessage);
return $results;
}
......@@ -1117,7 +1183,7 @@ class ArchiveTransfer extends \ext\demorm_publique\bundle\medona\Controller\abst
}
}
// Custom extraction scripts ?
// Custom extraction scripts ?
// Attach binary objects to documents
foreach ($archives as $archive) {
......
......@@ -260,9 +260,10 @@ class message extends \ext\thirdPartyArchiving\bundle\medona\Controller\message
*/
public function search($type, $reference = null, $archiver = null, $originator = null, $depositor = null, $archivalAgreement = null, $fromDate = null, $toDate = null, $isIncoming = null)
{
$queryParts = $this->searchMessage($type, $reference, $archiver, $originator, $depositor, $archivalAgreement, $fromDate, $toDate, $isIncoming);
$queryParams = array();
$queryString = $this->searchMessage($type, $reference, $archiver, $originator, $depositor, $archivalAgreement, $fromDate, $toDate, $isIncoming,$queryParams);
return $this->sdoFactory->find('medona/message', '('.implode(') and (', $queryParts).')', null, false, false, 300);
return $this->sdoFactory->find('medona/message', $queryString, $queryParams, false, false, 300);
}
/**
......@@ -278,7 +279,7 @@ class message extends \ext\thirdPartyArchiving\bundle\medona\Controller\message
*
* @return medona/message[]
*/
public function searchMessage($type, $reference = null, $archiver = null, $originator = null, $depositor = null, $archivalAgreement = null, $fromDate = null, $toDate = null, $isIncoming = null)
public function searchMessage($type, $reference = null, $archiver = null, $originator = null, $depositor = null, $archivalAgreement = null, $fromDate = null, $toDate = null, $isIncoming = null,&$queryParams)
{
$queryParts = array();
$currentService = \laabs::getToken("ORGANIZATION");
......@@ -288,20 +289,21 @@ class message extends \ext\thirdPartyArchiving\bundle\medona\Controller\message
$isArchiver = in_array('archiver', $currentService->orgRoleCodes);
$isControlAuthority = in_array('controlAuthority', $currentService->orgRoleCodes);
//if (!is_array($currentService->orgRoleCodes) || empty($currentService->orgRoleCodes)) {
// return array();
//}
if ($archiver || $originator || $depositor) {
$query = [];
if ($archiver) {
$query[] = "(senderOrgRegNumber='$archiver' OR recipientOrgRegNumber='$archiver')";
$query[] = "(senderOrgRegNumber= :archiver OR recipientOrgRegNumber= :archiver)";
$queryParams['archiver'] = $archiver;
}
if ($originator) {
$query[] = "(senderOrgRegNumber='$originator' OR recipientOrgRegNumber='$originator')";
$query[] = "(senderOrgRegNumber= :originator OR recipientOrgRegNumber= :originator)";
$queryParams['originator'] = $originator;
}
if ($depositor) {
$query[] = "(senderOrgRegNumber='$depositor' OR recipientOrgRegNumber='$depositor')";
$query[] = "(senderOrgRegNumber= :depositor OR recipientOrgRegNumber= :depositor)";
$queryParams['depositor'] = $depositor;
}
$size = sizeof($query);
......@@ -314,25 +316,29 @@ class message extends \ext\thirdPartyArchiving\bundle\medona\Controller\message
}
}
if ($archivalAgreement) {
$queryParts[] = "archivalAgreementReference='$archivalAgreement'";
$queryParts[] = "archivalAgreementReference= :archivalAgreementReference";
$queryParams['archivalAgreementReference'] = $archivalAgreement;
}
if ($fromDate) {
$fromDate = \laabs::newDate($fromDate, "Y-m-d H:i:s");
$queryParts[] = "date >='$fromDate'";
$queryParts[] = "date >= :fromDate";
$queryParams['fromDate'] = $fromDate;
}
if ($toDate) {
$toDate = \laabs::newDate($toDate, "Y-m-d H:i:s");
$toDate->add(new \DateInterval("PT23H59M59S"));
$queryParts[] = "date <='$toDate'";
$queryParts[] = "date <= :toDate";
$queryParams['toDate'] = $toDate;
}
if ($reference) {
$queryParts[] = "reference='$reference'";
$queryParts[] = "reference= :reference";
$queryParams['reference'] = $reference;
}
if ($isIncoming !== null) {
switch ($isIncoming) {
case true :
$queryParts[] = "isIncoming= true";
break;
break;
case false :
$queryParts[] = "isIncoming= false";
break;
......@@ -351,7 +357,7 @@ class message extends \ext\thirdPartyArchiving\bundle\medona\Controller\message
}
break;
case "ArchiveDestruction":
case "ArchiveDestruction":
if ($isArchiver) {
$clause[] = "type='*$type*'";
}
......@@ -368,7 +374,7 @@ class message extends \ext\thirdPartyArchiving\bundle\medona\Controller\message
}
break;
case "ArchiveRestitution":
$clause[] = "type=['ArchiveRestitutionRequest','ArchiveRestitution']";
break;
......@@ -376,26 +382,26 @@ class message extends \ext\thirdPartyArchiving\bundle\medona\Controller\message
case "ArchiveNotification":
$clause[] = "type=['ArchiveModificationNotification','ArchiveDestructionNotification','ArchivalProfileModificationNotification']";
break;
default :
$clause[] = "type='$type' AND status !='template'";
$clause[] = "type= :type AND status !='template'";
$queryParams['type'] = $type;
break;
}
if (!empty($clause)) {
$queryParts[] =
$queryParts[] =
'('
.\laabs\implode(') OR (', $clause)
.\laabs\implode(') OR (', $clause)
.')';
}
}
}
$orgUnitsClause = $this->getCurrentRegistrationNumber();
$currentServiceOrgRegNumber = $currentService->registrationNumber;
$queryParts[] = "(recipientOrgRegNumber= :currentServiceOrgRegNumber OR senderOrgRegNumber= :currentServiceOrgRegNumber)";
$queryParams['currentServiceOrgRegNumber'] = $currentServiceOrgRegNumber;
$queryParts[] = "(recipientOrgRegNumber='$currentServiceOrgRegNumber' OR senderOrgRegNumber='$currentServiceOrgRegNumber')";
return $queryParts;
return '('.implode(') and (', $queryParts).')';
}
/**
......@@ -455,8 +461,6 @@ class message extends \ext\thirdPartyArchiving\bundle\medona\Controller\message
*/
public function create($message)
{
$message->reference = $message->reference . "_" . \laabs::newTimestamp()->getTimestamp();
// Check unique
$unique = array(
'type' => $message->type,
......@@ -1078,9 +1082,11 @@ class message extends \ext\thirdPartyArchiving\bundle\medona\Controller\message
*/
public function getByReference($reference)
{
$queryParts = $this->searchMessage(null, $reference);
// $queryParts = $this->searchMessage(null, $reference);
$queryParams = array();
$queryString = $this->searchMessage(null, $reference, null, null, null, null, null, null, null,$queryParams);
$message = $this->sdoFactory->find('medona/message', '('.implode(') and (', $queryParts).')', null, false, false, 300);
$message = $this->sdoFactory->find('medona/message', $queryString, $queryParams, false, false, 300);
if (!$message) {
return null;
......
......@@ -33,15 +33,16 @@ class ArchiveTransferComposition extends \ext\archivesPubliques\bundle\seda2\Con
{
$message = $this->composeMessage($messageObject);
$message->messageId = \laabs::newId();
$message->isIncoming = true;
if ($isTemplate) {
$message->status = 'template';
}
$message->reference = $message->reference . "_" . \laabs::newTimestamp()->getTimestamp();
if ($this->sdoFactory->exists('medona/message', array('type'=>$message->type, 'senderOrgRegNumber'=>$message->senderOrgRegNumber, 'reference'=>$message->reference))) {
throw \laabs::newException("seda/invalidMessageException", "L'identifiant du message existe déjà.");
throw \laabs::newException("seda2/invalidMessageException", "L'identifiant du message existe déjà.");
}
$messageDir = $this->messageDirectory.DIRECTORY_SEPARATOR.(string) $message->messageId;
......
......@@ -26,18 +26,12 @@
Caps Lock On
</div>
<div style="color: red;">
<p>Ceci est une version de démo de Maarch RM V2.1 avec son extension "Archives Publiques" (<a href="//maarchrm.com/download/Maarch%20RM%20v2.1%20-%20Guide%20de%20visite%20sphère%20publique.pdf" target="_blank">Guide de visite</a>)</p>
<p>Le jeu de démo est disponible <a href="//maarchrm.com/download/ArchiveTransfer.zip" taget="_blank">ici</a></p>
<p>Prochaine remise à zéro des données à <?merge nextExecution ?> (Europe / Paris)</p>
<p>Ceci est une version de démo de Maarch RM V2.2 avec son extension "Archives Publiques" (<a href="//cdn.maarch.org/demorm/MaarchRMv2.2_GuideDeVisite_spherePublique.pdf" target="_blank">Guide de visite</a>)</p>
<p>Le jeu de démo est disponible <a href="//cdn.maarch.org/demorm/ArchiveTransfer_RM_AP.zip" target="_blank">ici</a></p>
<p>Prochaine remise à zéro des données à <?merge nextExecution ?> (Europe / Paris)</p>
<hr/>
<dl class="dl-horizontal">
<dt>Service versant<dt><dd>cchaplin/maarch</dd>
<dt>Archiviste</dt><dd>bblier/maarch</dd>
<dt>Service producteur<dt><dd>ccox/maarch</dd>
<dt>Autorité de Contrôle</dt><dd>sstallone/maarch</dd>
<dt>Service producteur</dt><dd>bbain/maarch</dd>
<dt>Archiviste<dt><dd>ddaull/maarch</dd>
<dt>Administrateur</dt><dd>superadmin/superadmin</dd>
</dl>
</div>
</div>
......@@ -49,6 +43,8 @@
</div>
</div>
<?hinclude auth/userAccount/login/forgotAccount.html ?>
<div class="modal fade" id="changePasswordModal">
<div class="modal-dialog">
<form>
......@@ -233,11 +229,11 @@
return;
}
var parameters = {
userName: userName,
oldPassword: password,
newPassword: $('#newPassword').val(),
requestPath: document.location.pathname,
};
userName: userName,
oldPassword: password,
newPassword: $('#newPassword').val(),
requestPath: document.location.pathname,
};
$.ajax({
type: "PUT",
url: "/user/password",
......
......@@ -9,7 +9,8 @@
<!--
stylesheets
-->
<link rel="stylesheet" href="/presentation/css/style.css" />
<!--<link rel="stylesheet" href="/presentation/css/style.css" />-->
<link rel="stylesheet" href="[?merge .css ?]" />
<!--link rel="stylesheet/less" type="text/css" href="/less/dashboard/style.less" /-->
......@@ -19,21 +20,26 @@
<!--jqueryui-->
<!-- script src="/public/js/jQueryUI_1.10.4/jqueryUI.js"></script -->
<!--less-->
<title><?merge .title ?> </title>
<script>
//less = {
// env: "development",
//};
</script>
<!-- Piwik -->
<!-- script type="text/javascript">
var _paq = _paq || [];
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//piwik.maarch.com/";
_paq.push(['setTrackerUrl', u+'piwik.php']);
_paq.push(['setSiteId', '6']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();
<script type="text/javascript">
var paq = paq || [];
/ tracker methods like "setCustomDimension" should be called before "trackPageView" /
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//piwik.maarch.com/";
_paq.push(['setTrackerUrl', u+'piwik.php']);
_paq.push(['setSiteId', '6']);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];