diff --git a/src/app/document/controllers/CertificateSignatureController.php b/src/app/document/controllers/CertificateSignatureController.php index d1965716abe0955a11b242dcf328a339c36b2ce6..f5b7e6c9631feae67dab9bb37af40466f93a49b3 100755 --- a/src/app/document/controllers/CertificateSignatureController.php +++ b/src/app/document/controllers/CertificateSignatureController.php @@ -262,12 +262,15 @@ class CertificateSignatureController 'fieldName' => $args['signatureFieldName'], 'extraCertificate' => $args['certificate'] ]); + if (!empty($signedDocumentPath['errors'])) { + return ['errors' => $signedDocumentPath['errors']]; + } } - if ($args['lastStep']) { - if ($args['signatureMode'] == 'rgs_2stars_timestamped') { - DigitalSignatureController::terminate(['config' => $config, 'transactionId' => $document['digital_signature_transaction_id']]); - } + if ($args['lastUserStep'] && $args['lastWorkflowStep'] && $args['signatureMode'] == 'rgs_2stars_timestamped') { + DigitalSignatureController::terminate(['config' => $config, 'transactionId' => $document['digital_signature_transaction_id']]); + } + if ($args['lastUserStep']) { $storeInfos = DocserverController::storeResourceOnDocServer([ 'encodedFile' => base64_encode(file_get_contents($signedDocumentPath)), 'format' => 'pdf', diff --git a/src/app/document/controllers/DigitalSignatureController.php b/src/app/document/controllers/DigitalSignatureController.php index b2409818782fe68ffb8747f0073986754c869685..6eeb13dc800055808de714ac525a77b4507c5eeb 100755 --- a/src/app/document/controllers/DigitalSignatureController.php +++ b/src/app/document/controllers/DigitalSignatureController.php @@ -279,8 +279,8 @@ class DigitalSignatureController $workflow = WorkflowModel::get([ 'select' => [1], - 'where' => ['mode = ?', 'main_document_id = ?', 'digital_signature_id != ?', 'process_date is null'], - 'data' => ['sign', $args['documentId'], $args['signatureId']] + 'where' => ['mode = ?', 'main_document_id = ?', "(digital_signature_id in ('1', '2') or digital_signature_id != ?)", 'process_date is null', 'id != ?'], + 'data' => ['sign', $args['documentId'], $args['signatureId'], $args['workflowId']] ]); if (empty($workflow) && $args['isLastSignature']) { diff --git a/src/app/document/controllers/DocumentController.php b/src/app/document/controllers/DocumentController.php index ab29ce646ab3cd6e386d68e79f21722cb10ceb16..b2cd37b8459b52873588a309522f0f60cb5d77c5 100755 --- a/src/app/document/controllers/DocumentController.php +++ b/src/app/document/controllers/DocumentController.php @@ -1009,9 +1009,9 @@ class DocumentController } if (DocumentController::ACTIONS[$args['actionId']] == 'VAL' && in_array($workflow['signature_mode'], ['rgs_2stars', 'rgs_2stars_timestamped', 'inca_card', 'inca_card_eidas'])) { - $lastStep = false; + $lastUserStep = false; if (empty($body['signatures']) || count($body['signatures']) == 1) { - $lastStep = true; + $lastUserStep = true; } $return = CertificateSignatureController::signDocument([ 'id' => $args['id'], @@ -1021,14 +1021,15 @@ class DocumentController 'hashSignature' => $body['hashSignature'], 'signatureMode' => $workflow['signature_mode'], 'tmpUniqueId' => $body['tmpUniqueId'] ?? null, - 'lastStep' => $lastStep + 'lastUserStep' => $lastUserStep, + 'lastWorkflowStep' => WorkflowModel::isLastStep(['id' => $workflow['id']]) ]); if (!empty($return['errors'])) { return $response->withStatus(400)->withJson($return); } - if (!$lastStep) { + if (!$lastUserStep) { return $response->withStatus(206)->withJson(['tmpUniqueId' => $body['tmpUniqueId']]); - } elseif ($lastStep && !empty($body['signatures'])) { + } elseif (!empty($body['signatures'])) { $storeInfos = DocserverController::storeResourceOnDocServer([ 'encodedFile' => base64_encode(file_get_contents("{$tmpPath}tmpSignatureDoc_{$GLOBALS['id']}_{$body['tmpUniqueId']}.pdf")), 'format' => 'pdf', @@ -1121,7 +1122,8 @@ class DocumentController 'filePath' => $imageTmpPath, 'signWidth' => $signWidth ], - 'isLastSignature' => !isset($body['signatures'][$key + 1]) + 'isLastSignature' => !isset($body['signatures'][$key + 1]), + 'workflowId' => $workflow['id'] ]); } else if ($loadedXml->metaSignSignature->enable == 'true' && $workflow['signature_mode'] == 'eidas_metasign') { $return = MetaSignSignatureController::signDocument([ @@ -1145,7 +1147,12 @@ class DocumentController } } if (!$imageSignature && $loadedXml->docaposteSignature->enable == 'true' && !empty($workflow['digital_signature_id']) && in_array($workflow['signature_mode'], ['eidas', 'inca_card_eidas'])) { - $return = DigitalSignatureController::signHashes(['signatureId' => $workflow['digital_signature_id'], 'documentId' => $args['id'], 'isLastSignature' => true]); + $return = DigitalSignatureController::signHashes([ + 'signatureId' => $workflow['digital_signature_id'], + 'documentId' => $args['id'], + 'workflowId' => $workflow['id'], + 'isLastSignature' => true + ]); if (!empty($return['errors'])) { return $response->withStatus(400)->withJson($return); } diff --git a/src/app/workflow/models/WorkflowModel.php b/src/app/workflow/models/WorkflowModel.php index dbea2341ca565b0e16a63ba896b75d1fb4acb2b2..9f886764c7d877bcd5c031edb3f0c6f667645598 100755 --- a/src/app/workflow/models/WorkflowModel.php +++ b/src/app/workflow/models/WorkflowModel.php @@ -80,6 +80,11 @@ class WorkflowModel return $workflow; } + /** + * returns the current step of a given document’s workflow + * + * a step is considered to be the current one if there are no processed steps after it. + */ public static function getCurrentStep(array $args) { ValidatorModel::notEmpty($args, ['select', 'documentId']); @@ -102,6 +107,28 @@ class WorkflowModel return $currentStep[0]; } + /** + * returns whether a workflow step identified by its id is the last in its own workflow + * + * does NOT depend on the workflow state: it may be processed or not, it only has to be the last one scheduled. + */ + public static function isLastStep(array $args) + { + ValidatorModel::notEmpty($args, ['id']); + ValidatorModel::intVal($args, ['id']); + + $return = DatabaseModel::select([ + 'select' => [1], + 'table' => ['workflows ws1', 'workflows ws2'], + 'left_join' => ['ws1.main_document_id = ws2.main_document_id'], + 'where' => ['ws1.id = ?', 'ws2.order > ws1.order'], + 'data' => [$args['id']], + 'limit' => 1 + ]); + + return empty($return); + } + public static function getWorkflowWithExternalInfo(array $aArgs) { ValidatorModel::arrayType($aArgs, ['select', 'orderBy', 'where', 'data']); diff --git a/src/frontend/app/service/auth.guard.ts b/src/frontend/app/service/auth.guard.ts index cde7ffb9a6ffb343ab96aeb37387dd48e2f948fc..a34137644dada64bbc587ee0d8da19388a67117f 100644 --- a/src/frontend/app/service/auth.guard.ts +++ b/src/frontend/app/service/auth.guard.ts @@ -28,13 +28,13 @@ export class AuthGuard implements CanActivate { public dialog: MatDialog, private menu: MenuController) { } - canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean { + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> | boolean { if (route.url.join('/') === 'login') { if (this.authService.isAuth()) { this.router.navigate(['/home']); return false; } else { - this.http.get('../rest/authenticationInformations').pipe( + return this.http.get('../rest/authenticationInformations').pipe( map((data: any) => { this.authService.loginMessage = data.loginMessage; this.authService.authMode = data.connection; @@ -42,9 +42,9 @@ export class AuthGuard implements CanActivate { this.authService.coreUrl = data.coreUrl; this.authService.mailServerOnline = data.mailServerOnline; this.localStorage.setAppSession(data.instanceId); + return true; }) - ). subscribe(); - return true; + ); } } else if (!this.authService.authFailed) { this.menu.enable(true, 'left-menu');