From 5b13aa558481d5abaffb78d697dd2582ebec2828 Mon Sep 17 00:00:00 2001
From: Damien <damien.burel@maarch.org>
Date: Wed, 12 May 2021 14:34:46 +0200
Subject: [PATCH] FEAT #16982 TIME 4:30 WIP External yousign workflow + fix
 workflow without userId + take care of security

---
 .../controllers/DocumentController.php        | 58 ++++++++++--------
 .../search/controllers/SearchController.php   | 15 ++++-
 .../controllers/YousignController.php         | 59 +++++++++++++++----
 .../WorkflowExternalInformationModel.php      | 20 +++++++
 4 files changed, 116 insertions(+), 36 deletions(-)

diff --git a/src/app/document/controllers/DocumentController.php b/src/app/document/controllers/DocumentController.php
index 18ed05c39f..1b851314ab 100755
--- a/src/app/document/controllers/DocumentController.php
+++ b/src/app/document/controllers/DocumentController.php
@@ -177,7 +177,7 @@ class DocumentController
             }
         }
 
-        $workflow = WorkflowModel::getByDocumentId(['select' => ['user_id', 'mode', 'process_date', 'signature_mode', 'status', 'note', 'signature_positions', 'date_positions'], 'documentId' => $args['id'], 'orderBy' => ['"order"']]);
+        $workflow = WorkflowModel::getByDocumentId(['select' => ['id', 'user_id', 'mode', 'process_date', 'signature_mode', 'status', 'note', 'signature_positions', 'date_positions'], 'documentId' => $args['id'], 'orderBy' => ['"order"']]);
         $currentFound = false;
         $currentId = null;
         foreach ($workflow as $value) {
@@ -185,18 +185,26 @@ class DocumentController
                 $date = new \DateTime($value['process_date']);
                 $value['process_date'] = $date->format('d-m-Y H:i');
             }
-            $userSignaturesModes = UserModel::getById(['id' => $value['user_id'], 'select' => ['signature_modes']]);
-
+            $userLabel = '';
+            if (!empty($value['user_id'])) {
+                $userSignaturesModes = UserModel::getById(['id' => $value['user_id'], 'select' => ['signature_modes']]);
+                $userLabel = UserModel::getLabelledUserById(['id' => $value['user_id']]);
+            } else {
+                $workflowExternalInformations = WorkflowExternalInformationModel::get(['select' => ['*'], 'where' => ['workflow_id = ?'], 'data' => [$value['id']]]);
+                if (!empty($workflowExternalInformations[0])) {
+                    $userLabel = "{$workflowExternalInformations[0]['firstname']} {$workflowExternalInformations[0]['lastname']}";
+                }
+            }
             $formattedDocument['workflow'][] = [
                 'userId'                => $value['user_id'],
-                'userDisplay'           => UserModel::getLabelledUserById(['id' => $value['user_id']]),
+                'userDisplay'           => $userLabel,
                 'mode'                  => $value['mode'],
                 'processDate'           => $value['process_date'],
                 'current'               => !$currentFound && empty($value['status']),
                 'signatureMode'         => $value['signature_mode'],
                 'signaturePositions'    => json_decode($value['signature_positions'], true),
                 'datePositions'         => json_decode($value['date_positions'], true),
-                'userSignatureModes'    => json_decode($userSignaturesModes['signature_modes'], true) ?? [],
+                'userSignatureModes'    => !empty($userSignaturesModes['signature_modes']) ? json_decode($userSignaturesModes['signature_modes'], true) : [],
                 'note'                  => $value['note'],
                 'status'                => $value['status']
             ];
@@ -325,6 +333,7 @@ class DocumentController
         $hasEidas = false;
         $hasElectronicSignature = false;
         foreach ($body['workflow'] as $key => $workflow) {
+            $processingUser = null;
             if (empty($workflow['processingUser']) && empty($workflow['userId']) && !empty($workflow['externalInformations'])) {
                 if (!Validator::stringType()->notEmpty()->validate($workflow['externalInformations']['firstname'] ?? null)) {
                     return $response->withStatus(400)->withJson(['errors' => "Body workflow[{$key}][externalInformations] firstname is empty or not a string"]);
@@ -509,13 +518,17 @@ class DocumentController
                     $firstWorkflowId = $workflowId;
                 }
                 if (empty($workflow['userId'])) {
+                    $informations = [];
+                    if ($workflow['externalInformations']['type'] == 'yousign') {
+                        $informations = YousignController::formatExternalInformations($workflow['externalInformations']);
+                    }
                     WorkflowExternalInformationModel::create([
                         'workflow_id'   => $workflowId,
                         'firstname'     => $workflow['externalInformations']['firstname'],
                         'lastname'      => $workflow['externalInformations']['lastname'],
                         'email'         => $workflow['externalInformations']['email'],
                         'phone'         => $workflow['externalInformations']['phone'],
-                        'informations'  => empty($workflow['externalInformations']['informations']) ? '{}' : json_encode($workflow['externalInformations']['informations'])
+                        'informations'  => json_encode($informations)
                     ]);
                 }
             }
@@ -567,17 +580,19 @@ class DocumentController
         }
 
         if (empty($body['workflow'][0]['userId'])) {
-            YousignController::createProcedure([
-                'encodedDocument'   => $encodedDocument['encodedDocument'],
-                'name'              => $body['title'],
-                'description'       => $body['description'],
-                'firstname'         => $body['workflow'][0]['externalInformations']['firstname'],
-                'lastname'          => $body['workflow'][0]['externalInformations']['lastname'],
-                'email'             => $body['workflow'][0]['externalInformations']['email'],
-                'phone'             => $body['workflow'][0]['externalInformations']['phone'],
-                'position'          => "364,105,462,145",
-                'workflowId'        => $firstWorkflowId
-            ]);
+            if ($body['workflow'][0]['externalInformations']['type'] == 'yousign') {
+                $procedureCreated = YousignController::createProcedure([
+                    'documentId'        => $id,
+                    'encodedDocument'   => $encodedDocument['encodedDocument'],
+                    'name'              => $body['title'],
+                    'description'       => $body['description'],
+                    'position'          => "364,105,462,145",
+                    'workflowId'        => $firstWorkflowId
+                ]);
+                if (!empty($procedureCreated['errors'])) {
+                    return $response->withStatus(500)->withJson(['errors' => 'Yousign procedure creation failed : ' . $procedureCreated['errors']]);
+                }
+            }
         } else {
             EmailController::sendNotification(['documentId' => $id, 'userId' => $GLOBALS['id']]);
         }
@@ -1012,8 +1027,8 @@ class DocumentController
 
     public static function endAction(array $args)
     {
-        ValidatorModel::notEmpty($args, ['id', 'status', 'workflowId', 'userId']);
-        ValidatorModel::intVal($args, ['id', 'workflowId', 'userId']);
+        ValidatorModel::notEmpty($args, ['id', 'status', 'workflowId']);
+        ValidatorModel::intVal($args, ['id', 'workflowId']);
         ValidatorModel::stringType($args, ['status', 'note']);
 
         $set = ['process_date' => 'CURRENT_TIMESTAMP', 'status' => $args['status']];
@@ -1043,13 +1058,10 @@ class DocumentController
                 $document = DocumentModel::getById(['select' => ['title', 'description'], 'id' => $args['id']]);
 
                 YousignController::createProcedure([
+                    'documentId'        => $args['id'],
                     'encodedDocument'   => base64_encode($content),
                     'name'              => $document['title'],
                     'description'       => $document['description'],
-                    'firstname'         => $workflowExternalInformations[0]['firstname'],
-                    'lastname'          => $workflowExternalInformations[0]['lastname'],
-                    'email'             => $workflowExternalInformations[0]['email'],
-                    'phone'             => $workflowExternalInformations[0]['phone'],
                     'position'          => "364,105,462,145",
                     'workflowId'        => $nextWorkflow['id']
                 ]);
diff --git a/src/app/search/controllers/SearchController.php b/src/app/search/controllers/SearchController.php
index 30632ff0d5..d824c1aef8 100755
--- a/src/app/search/controllers/SearchController.php
+++ b/src/app/search/controllers/SearchController.php
@@ -21,6 +21,7 @@ use Slim\Http\Request;
 use Slim\Http\Response;
 use SrcCore\models\ValidatorModel;
 use User\models\UserModel;
+use Workflow\models\WorkflowExternalInformationModel;
 use Workflow\models\WorkflowModel;
 
 class SearchController
@@ -123,7 +124,7 @@ class SearchController
         $count = empty($documents[0]['count']) ? 0 : $documents[0]['count'];
         $hasIndexation = PrivilegeController::hasPrivilege(['userId' => $GLOBALS['id'], 'privilege' => 'indexation']);
         foreach ($documents as $key => $document) {
-            $workflow          = WorkflowModel::getByDocumentId(['select' => ['user_id', 'mode', 'process_date', 'signature_mode', 'note', 'status'], 'documentId' => $document['id'], 'orderBy' => ['"order"']]);
+            $workflow          = WorkflowModel::getByDocumentId(['select' => ['id', 'user_id', 'mode', 'process_date', 'signature_mode', 'note', 'status'], 'documentId' => $document['id'], 'orderBy' => ['"order"']]);
             $currentFound      = false;
             $formattedWorkflow = [];
             $state             = null;
@@ -133,9 +134,19 @@ class SearchController
                     $value['process_date'] = $date->format('d-m-Y H:i');
                 }
 
+                $userLabel = '';
+                if (!empty($value['user_id'])) {
+                    $userLabel = UserModel::getLabelledUserById(['id' => $value['user_id']]);
+                } else {
+                    $workflowExternalInformations = WorkflowExternalInformationModel::getByWorkflowId(['select' => ['firstname', 'lastname'], 'workflowId' => $value['id']]);
+                    if (!empty($workflowExternalInformations[0])) {
+                        $userLabel = "{$workflowExternalInformations[0]['firstname']} {$workflowExternalInformations[0]['lastname']}";
+                    }
+                }
+
                 $formattedWorkflow[] = [
                     'userId'        => $value['user_id'],
-                    'userDisplay'   => UserModel::getLabelledUserById(['id' => $value['user_id']]),
+                    'userDisplay'   => $userLabel,
                     'mode'          => $value['mode'],
                     'processDate'   => $value['process_date'],
                     'current'       => !$currentFound && empty($value['status']),
diff --git a/src/app/workflow/controllers/YousignController.php b/src/app/workflow/controllers/YousignController.php
index 4878321579..50988af6c6 100755
--- a/src/app/workflow/controllers/YousignController.php
+++ b/src/app/workflow/controllers/YousignController.php
@@ -19,7 +19,9 @@ use Docserver\models\AdrModel;
 use Document\controllers\DocumentController;
 use Slim\Http\Request;
 use Slim\Http\Response;
+use SrcCore\controllers\UrlController;
 use SrcCore\models\CurlModel;
+use SrcCore\models\ValidatorModel;
 use Workflow\models\WorkflowExternalInformationModel;
 use Workflow\models\WorkflowModel;
 
@@ -30,6 +32,13 @@ class YousignController
         $url = 'https://staging-api.yousign.com';
         $token = '';
 
+        $workflowExternalInformations = WorkflowExternalInformationModel::getByWorkflowId(['select' => ['*'], 'workflowId' => $args['workflowId']]);
+        if (empty($workflowExternalInformations)) {
+            return ['errors' => 'No external informations found'];
+        }
+
+        $workflowExternalInformations['informations'] = json_decode($workflowExternalInformations['informations'], true);
+
         $fileResponse = CurlModel::exec([
             'url'           => "{$url}/files",
             'bearerAuth'    => ['token' => $token],
@@ -46,6 +55,7 @@ class YousignController
         }
 
         $fileId = $fileResponse['response']['id'];
+        $trunkedFileId = str_replace('/files/', '', $fileId);
 
         $procedureResponse = CurlModel::exec([
             'url'           => "{$url}/procedures",
@@ -57,10 +67,12 @@ class YousignController
                 'description'   => $args['description'],
                 'members'       => [
                     [
-                        'firstname' => $args['firstname'],
-                        'lastname'  => $args['lastname'],
-                        'email'     => $args['email'],
-                        'phone'     => $args['phone'],
+                        'firstname'             => $workflowExternalInformations['firstname'],
+                        'lastname'              => $workflowExternalInformations['lastname'],
+                        'email'                 => $workflowExternalInformations['email'],
+                        'phone'                 => $workflowExternalInformations['phone'],
+                        'operationLevel'        => 'custom',
+                        'operationCustomModes'  => [$workflowExternalInformations['informations']['security']],
                         'fileObjects'   => [
                             [
                                 'file'      => $fileId,
@@ -79,16 +91,25 @@ class YousignController
                                 "to"        => ["@member"]
                             ]
                         ]
-                    ]
+                    ],
+//                    'webhook'   => [
+//                        'member.finished' => [
+//                            [
+//                                'url'       => UrlController::getCoreUrl() . "/rest/documents/{$args['documentId']}/workflows/{$args['workflowId']}/files/{$trunkedFileId}",
+//                                'method'    => 'GET',
+//                            ]
+//                        ]
+//                    ]
                 ]
             ])
         ]);
-
         if ($procedureResponse['code'] != 201) {
             return ['errors' => json_encode($procedureResponse['reponse'])];
         }
 
-        $informations = json_encode(['yousignFileId' => $fileId]);
+
+        $workflowExternalInformations['informations']['yousignFileId'] = $fileId;
+        $informations = json_encode($workflowExternalInformations['informations']);
         WorkflowExternalInformationModel::update(['set' => ['informations' => $informations], 'where' => ['workflow_id = ?'], 'data' => [$args['workflowId']]]);
 
         return true;
@@ -129,7 +150,7 @@ class YousignController
         }
 
         $storeInfos = DocserverController::storeResourceOnDocServer([
-            'encodedFile'     => $fileResponse['reponse'],
+            'encodedFile'     => $fileResponse['response'],
             'format'          => 'pdf',
             'docserverType'   => 'DOC'
         ]);
@@ -151,11 +172,27 @@ class YousignController
 
         DocumentController::endAction([
             'id'            => $args['id'],
-            'workflowId'    => $workflow['id'],
-            'status'        => DocumentController::ACTIONS[$args['actionId']],
-            'note'          => $body['note'] ?? null
+            'workflowId'    => $args['workflowId'],
+            'status'        => 'VAL',
+            'note'          => null
         ]);
 
         return true;
     }
+
+    public static function formatExternalInformations(array $args)
+    {
+        ValidatorModel::stringType($args, ['security']);
+
+        $informations = [
+            'type'      => 'yousign',
+            'security'  => 'sms'
+        ];
+
+        if (!empty($args['security']) && $args['security'] == 'email') {
+            $informations['security'] = 'email';
+        }
+
+        return $informations;
+    }
 }
diff --git a/src/app/workflow/models/WorkflowExternalInformationModel.php b/src/app/workflow/models/WorkflowExternalInformationModel.php
index 176f345757..fc0a48f64a 100755
--- a/src/app/workflow/models/WorkflowExternalInformationModel.php
+++ b/src/app/workflow/models/WorkflowExternalInformationModel.php
@@ -39,6 +39,26 @@ class WorkflowExternalInformationModel
         return $workflows;
     }
 
+    public static function getByWorkflowId(array $args)
+    {
+        ValidatorModel::notEmpty($args, ['select', 'workflowId']);
+        ValidatorModel::intVal($args, ['workflowId']);
+        ValidatorModel::arrayType($args, ['select']);
+
+        $workflow = DatabaseModel::select([
+            'select'    => $args['select'],
+            'table'     => ['workflows_external_informations'],
+            'where'     => ['workflow_id = ?'],
+            'data'      => [$args['workflowId']]
+        ]);
+
+        if (empty($workflow[0])) {
+            return [];
+        }
+
+        return $workflow[0];
+    }
+
     public static function create(array $args)
     {
         ValidatorModel::notEmpty($args, ['workflow_id', 'firstname', 'lastname']);
-- 
GitLab