From 5adb0ccd6445ed575fc5756125ab8daefd24c10f Mon Sep 17 00:00:00 2001 From: Thibault Dockx <thibault.dockx@fusiondirectory.org> Date: Thu, 27 Mar 2025 11:46:12 +0000 Subject: [PATCH 1/3] :art: refactor(archive) - improve method structure and enhance supann status handling in archiving process --- plugins/tasks/Archive.php | 250 ++++++++++++++++++++------------------ 1 file changed, 133 insertions(+), 117 deletions(-) diff --git a/plugins/tasks/Archive.php b/plugins/tasks/Archive.php index 2ef3e2f..a5d32b5 100644 --- a/plugins/tasks/Archive.php +++ b/plugins/tasks/Archive.php @@ -4,134 +4,150 @@ use FusionDirectory\Rest\WebServiceCall; class Archive implements EndpointInterface { - private TaskGateway $gateway; - - public function __construct (TaskGateway $gateway) - { - $this->gateway = $gateway; - } - - /** - * @return array - * Part of the interface of orchestrator plugin to treat GET method - */ - public function processEndPointGet (): array - { - // Retrieve tasks of type 'archive' - return $this->gateway->getObjectTypeTask('archive'); - } - - /** - * @param array|null $data - * @return array - * @throws Exception - * Note: Part of the interface of orchestrator plugin to treat PATCH method - */ - public function processEndPointPatch (array $data = NULL): array - { - $result = []; - $archiveTasks = $this->gateway->getObjectTypeTask('archive'); - - // Initialize the WebServiceCall object for login - $webServiceCall = new WebServiceCall($_ENV['FUSION_DIRECTORY_API_URL'] . '/login', 'POST'); - $webServiceCall->setCurlSettings(); // Perform login and set the token - - foreach ($archiveTasks as $task) { - try { - if (!$this->gateway->statusAndScheduleCheck($task)) { - // Skip this task if it does not meet the status and schedule criteria - continue; - } + private TaskGateway $gateway; - // Receive null or 'toBeArchived' - $supannState = $this->getUserSupannAccountStatus($task['fdtasksgranulardn'][0]); + public function __construct(TaskGateway $gateway) + { + $this->gateway = $gateway; + } - if ($supannState !== 'toBeArchived') { - // The task does not meet the criteria for archiving and can therefore be suppressed - $result[$task['dn']]['result'] = "User does not meet the criteria for archiving."; - $this->gateway->removeSubTask($task['dn']); - continue; - } + /** + * @return array + * Part of the interface of orchestrator plugin to treat GET method + */ + public function processEndPointGet(): array + { + // Retrieve tasks of type 'archive' + return $this->gateway->getObjectTypeTask('archive'); + } - // Set the archive endpoint and method using the same WebServiceCall object - $archiveUrl = $_ENV['FUSION_DIRECTORY_API_URL'] . '/archive/user/' . rawurlencode($task['fdtasksgranulardn'][0]); - $webServiceCall->setCurlSettings($archiveUrl, NULL, 'POST'); // Update settings for the archive request - $response = $webServiceCall->execute(); - - // Check if the HTTP status code is 204 - if ($webServiceCall->getHttpStatusCode() === 204) { - $result[$task['dn']]['result'] = "User successfully archived."; - $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], '2'); - } else { - throw new Exception("Unexpected HTTP status code: " . $webServiceCall->getHttpStatusCode()); + /** + * @param array|null $data + * @return array + * @throws Exception + * Note: Part of the interface of orchestrator plugin to treat PATCH method + */ + public function processEndPointPatch(array $data = null): array + { + $result = []; + $archiveTasks = $this->gateway->getObjectTypeTask('archive'); + + // Initialize the WebServiceCall object for login + $webServiceCall = new WebServiceCall($_ENV['FUSION_DIRECTORY_API_URL'] . '/login', 'POST'); + $webServiceCall->setCurlSettings(); // Perform login and set the token + + foreach ($archiveTasks as $task) { + try { + if (!$this->gateway->statusAndScheduleCheck($task)) { + // Skip this task if it does not meet the status and schedule criteria + continue; + } + + // Retrieve the desired supann status from the main task + $desiredSupannStatus = $this->getArchiveTaskBehaviorFromMainTask($task['fdtasksgranularmaster'][0]); + + // Retrieve the current supann status of the user + $currentSupannStatus = $this->getUserSupannAccountStatus($task['fdtasksgranulardn'][0]); + + // Check if the current supann status matches the desired status + if (!$this->isSupannStatusMatching($desiredSupannStatus, $currentSupannStatus)) { + // The task does not meet the criteria for archiving and can therefore be suppressed + $result[$task['dn']]['result'] = "User does not meet the criteria for archiving."; + $this->gateway->removeSubTask($task['dn']); + continue; + } + + // Set the archive endpoint and method using the same WebServiceCall object + $archiveUrl = $_ENV['FUSION_DIRECTORY_API_URL'] . '/archive/user/' . rawurlencode($task['fdtasksgranulardn'][0]); + $webServiceCall->setCurlSettings($archiveUrl, null, 'POST'); // Update settings for the archive request + $response = $webServiceCall->execute(); + + // Check if the HTTP status code is 204 + if ($webServiceCall->getHttpStatusCode() === 204) { + $result[$task['dn']]['result'] = "User successfully archived."; + $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], '2'); + } else { + throw new Exception("Unexpected HTTP status code: " . $webServiceCall->getHttpStatusCode()); + } + } catch (Exception $e) { + $result[$task['dn']]['result'] = "Error archiving user: " . $e->getMessage(); + $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], $e->getMessage()); + } } - } catch (Exception $e) { - $result[$task['dn']]['result'] = "Error archiving user: " . $e->getMessage(); - $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], $e->getMessage()); - } - } - return $result; - } - - /** - * @param array|null $data - * @return array - * Note: Part of the interface of orchestrator plugin to treat POST method - */ - public function processEndPointPost (array $data = NULL): array - { - return []; - } - - /** - * @param array|null $data - * @return array - * Note: Part of the interface of orchestrator plugin to treat DELETE method - */ - public function processEndPointDelete (array $data = NULL): array - { - return []; - } - - /** - * Retrieve the supannAccountStatus of a user - * @param string $userDn - * @return string|null - */ - private function getUserSupannAccountStatus (string $userDn): ?string - { - $supannState = $this->gateway->getLdapTasks( - '(objectClass=supannPerson)', - ['supannRessourceEtatDate'], - '', - $userDn - ); - - if ($this->hasToBeArchived($supannState)) { - return 'toBeArchived'; + return $result; } - return NULL; - } + /** + * @param array|null $data + * @return array + * Note: Part of the interface of orchestrator plugin to treat POST method + */ + public function processEndPointPost(array $data = null): array + { + return []; + } - private function hasToBeArchived (array $supannState): bool - { - if (!isset($supannState[0]['supannressourceetatdate']) || !is_array($supannState[0]['supannressourceetatdate'])) { - return FALSE; + /** + * @param array|null $data + * @return array + * Note: Part of the interface of orchestrator plugin to treat DELETE method + */ + public function processEndPointDelete(array $data = null): array + { + return []; } - foreach ($supannState[0]['supannressourceetatdate'] as $key => $value) { - // Skip non-numeric keys (e.g., 'count') - if (!is_numeric($key)) { - continue; - } + /** + * Retrieve the supannAccountStatus of a user + * @param string $userDn + * @return array|null + */ + private function getUserSupannAccountStatus(string $userDn): ?array + { + return $this->gateway->getLdapTasks( + '(objectClass=supannPerson)', + ['supannRessourceEtatDate'], + '', + $userDn + ); + } - if (strpos($value, '{COMPTE}I:toBeArchived') !== FALSE) { - return TRUE; - } + /** + * @param string $taskDN + * @return array + * Note: Retrieve the desired supann status from the main task attributes. + */ + private function getArchiveTaskBehaviorFromMainTask(string $taskDN): array + { + return $this->gateway->getLdapTasks( + '(objectClass=*)', + ['fdArchiveTaskResource', 'fdArchiveTaskState', 'fdArchiveTaskSubState'], + '', + $taskDN + ); } - return FALSE; - } + /** + * @param array $desiredStatus + * @param array $currentStatus + * @return bool + * Note: Compare the desired supann status with the current status to determine if they match. + */ + private function isSupannStatusMatching(array $desiredStatus, array $currentStatus): bool + { + if (empty($currentStatus[0]['supannressourceetatdate'])) { + return false; + } + + foreach ($currentStatus[0]['supannressourceetatdate'] as $resource) { + if (strpos($resource, '{' . $desiredStatus[0]['fdarchivetaskresource'][0] . '}') !== false && + strpos($resource, ':' . $desiredStatus[0]['fdarchivetaskstate'][0]) !== false && + (empty($desiredStatus[0]['fdarchivetasksubstate'][0]) || strpos($resource, ':' . $desiredStatus[0]['fdarchivetasksubstate'][0]) !== false)) { + return true; + } + } + + return false; + } } \ No newline at end of file -- GitLab From f05c3a412a26d3696f1ce7eba43bec6de3d3842e Mon Sep 17 00:00:00 2001 From: Thibault Dockx <thibault.dockx@fusiondirectory.org> Date: Mon, 31 Mar 2025 15:04:56 +0100 Subject: [PATCH 2/3] :art: style(archive) - improve code formatting and enhance readability in Archive.php --- plugins/tasks/Archive.php | 224 ++++++++++++++++++++++---------------- 1 file changed, 128 insertions(+), 96 deletions(-) diff --git a/plugins/tasks/Archive.php b/plugins/tasks/Archive.php index a5d32b5..d4ace78 100644 --- a/plugins/tasks/Archive.php +++ b/plugins/tasks/Archive.php @@ -4,22 +4,22 @@ use FusionDirectory\Rest\WebServiceCall; class Archive implements EndpointInterface { - private TaskGateway $gateway; + private TaskGateway $gateway; - public function __construct(TaskGateway $gateway) - { - $this->gateway = $gateway; - } + public function __construct (TaskGateway $gateway) + { + $this->gateway = $gateway; + } /** * @return array * Part of the interface of orchestrator plugin to treat GET method */ - public function processEndPointGet(): array - { - // Retrieve tasks of type 'archive' - return $this->gateway->getObjectTypeTask('archive'); - } + public function processEndPointGet (): array + { + // Retrieve tasks of type 'archive' + return $this->gateway->getObjectTypeTask('archive'); + } /** * @param array|null $data @@ -27,106 +27,106 @@ class Archive implements EndpointInterface * @throws Exception * Note: Part of the interface of orchestrator plugin to treat PATCH method */ - public function processEndPointPatch(array $data = null): array - { - $result = []; - $archiveTasks = $this->gateway->getObjectTypeTask('archive'); - - // Initialize the WebServiceCall object for login - $webServiceCall = new WebServiceCall($_ENV['FUSION_DIRECTORY_API_URL'] . '/login', 'POST'); - $webServiceCall->setCurlSettings(); // Perform login and set the token - - foreach ($archiveTasks as $task) { - try { - if (!$this->gateway->statusAndScheduleCheck($task)) { - // Skip this task if it does not meet the status and schedule criteria - continue; - } - - // Retrieve the desired supann status from the main task - $desiredSupannStatus = $this->getArchiveTaskBehaviorFromMainTask($task['fdtasksgranularmaster'][0]); - - // Retrieve the current supann status of the user - $currentSupannStatus = $this->getUserSupannAccountStatus($task['fdtasksgranulardn'][0]); - - // Check if the current supann status matches the desired status - if (!$this->isSupannStatusMatching($desiredSupannStatus, $currentSupannStatus)) { - // The task does not meet the criteria for archiving and can therefore be suppressed - $result[$task['dn']]['result'] = "User does not meet the criteria for archiving."; - $this->gateway->removeSubTask($task['dn']); - continue; - } - - // Set the archive endpoint and method using the same WebServiceCall object - $archiveUrl = $_ENV['FUSION_DIRECTORY_API_URL'] . '/archive/user/' . rawurlencode($task['fdtasksgranulardn'][0]); - $webServiceCall->setCurlSettings($archiveUrl, null, 'POST'); // Update settings for the archive request - $response = $webServiceCall->execute(); - - // Check if the HTTP status code is 204 - if ($webServiceCall->getHttpStatusCode() === 204) { - $result[$task['dn']]['result'] = "User successfully archived."; - $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], '2'); - } else { - throw new Exception("Unexpected HTTP status code: " . $webServiceCall->getHttpStatusCode()); - } - } catch (Exception $e) { - $result[$task['dn']]['result'] = "Error archiving user: " . $e->getMessage(); - $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], $e->getMessage()); - } + public function processEndPointPatch (array $data = NULL): array + { + $result = []; + $archiveTasks = $this->gateway->getObjectTypeTask('archive'); + + // Initialize the WebServiceCall object for login + $webServiceCall = new WebServiceCall($_ENV['FUSION_DIRECTORY_API_URL'] . '/login', 'POST'); + $webServiceCall->setCurlSettings(); // Perform login and set the token + + foreach ($archiveTasks as $task) { + try { + if (!$this->gateway->statusAndScheduleCheck($task)) { + // Skip this task if it does not meet the status and schedule criteria + continue; + } + + // Retrieve the desired supann status from the main task + $desiredSupannStatus = $this->getArchiveTaskBehaviorFromMainTask($task['fdtasksgranularmaster'][0]); + + // Retrieve the current supann status of the user + $currentSupannStatus = $this->getUserSupannAccountStatus($task['fdtasksgranulardn'][0]); + + // Check if the current supann status matches the desired status + if (!$this->isSupannStatusMatching($desiredSupannStatus, $currentSupannStatus)) { + // The task does not meet the criteria for archiving and can therefore be suppressed + $result[$task['dn']]['result'] = "User does not meet the criteria for archiving."; + $this->gateway->removeSubTask($task['dn']); + continue; } - return $result; + // Set the archive endpoint and method using the same WebServiceCall object + $archiveUrl = $_ENV['FUSION_DIRECTORY_API_URL'] . '/archive/user/' . rawurlencode($task['fdtasksgranulardn'][0]); + $webServiceCall->setCurlSettings($archiveUrl, NULL, 'POST'); // Update settings for the archive request + $response = $webServiceCall->execute(); + + // Check if the HTTP status code is 204 + if ($webServiceCall->getHttpStatusCode() === 204) { + $result[$task['dn']]['result'] = "User " . $task['fdtasksgranulardn'][0] . " successfully archived."; + $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], '2'); + } else { + throw new Exception("Unexpected HTTP status code: " . $webServiceCall->getHttpStatusCode()); + } + } catch (Exception $e) { + $result[$task['dn']]['result'] = "Error archiving user: " . $e->getMessage(); + $this->gateway->updateTaskStatus($task['dn'], $task['cn'][0], $e->getMessage()); + } } + return $result; + } + /** * @param array|null $data * @return array * Note: Part of the interface of orchestrator plugin to treat POST method */ - public function processEndPointPost(array $data = null): array - { - return []; - } + public function processEndPointPost (array $data = NULL): array + { + return []; + } /** * @param array|null $data * @return array * Note: Part of the interface of orchestrator plugin to treat DELETE method */ - public function processEndPointDelete(array $data = null): array - { - return []; - } + public function processEndPointDelete (array $data = NULL): array + { + return []; + } /** * Retrieve the supannAccountStatus of a user * @param string $userDn * @return array|null */ - private function getUserSupannAccountStatus(string $userDn): ?array - { - return $this->gateway->getLdapTasks( - '(objectClass=supannPerson)', - ['supannRessourceEtatDate'], - '', - $userDn - ); - } + private function getUserSupannAccountStatus (string $userDn): ?array + { + return $this->gateway->getLdapTasks( + '(objectClass=supannPerson)', + ['supannRessourceEtatDate'], + '', + $userDn + ); + } /** * @param string $taskDN * @return array * Note: Retrieve the desired supann status from the main task attributes. */ - private function getArchiveTaskBehaviorFromMainTask(string $taskDN): array - { - return $this->gateway->getLdapTasks( - '(objectClass=*)', - ['fdArchiveTaskResource', 'fdArchiveTaskState', 'fdArchiveTaskSubState'], - '', - $taskDN - ); - } + private function getArchiveTaskBehaviorFromMainTask (string $taskDN): array + { + return $this->gateway->getLdapTasks( + '(objectClass=*)', + ['fdArchiveTaskResource', 'fdArchiveTaskState', 'fdArchiveTaskSubState'], + '', + $taskDN + ); + } /** * @param array $desiredStatus @@ -134,20 +134,52 @@ class Archive implements EndpointInterface * @return bool * Note: Compare the desired supann status with the current status to determine if they match. */ - private function isSupannStatusMatching(array $desiredStatus, array $currentStatus): bool - { - if (empty($currentStatus[0]['supannressourceetatdate'])) { - return false; - } + private function isSupannStatusMatching (array $desiredStatus, array $currentStatus): bool + { + if (empty($currentStatus[0]['supannressourceetatdate'])) { + return FALSE; + } - foreach ($currentStatus[0]['supannressourceetatdate'] as $resource) { - if (strpos($resource, '{' . $desiredStatus[0]['fdarchivetaskresource'][0] . '}') !== false && - strpos($resource, ':' . $desiredStatus[0]['fdarchivetaskstate'][0]) !== false && - (empty($desiredStatus[0]['fdarchivetasksubstate'][0]) || strpos($resource, ':' . $desiredStatus[0]['fdarchivetasksubstate'][0]) !== false)) { - return true; - } - } + // Extract the desired attributes + $desiredAttributes = $this->extractDesiredAttributes($desiredStatus); - return false; + if (!$desiredAttributes['resource'] || !$desiredAttributes['state']) { + return FALSE; } + + // Check if any of the current supannressourceetatdate values match the desired attributes + foreach ($currentStatus[0]['supannressourceetatdate'] as $key => $resource) { + if (!is_numeric($key)) { + continue; + } + + if ($this->doesResourceMatch($resource, $desiredAttributes)) { + return TRUE; + } + } + + return FALSE; + } + + private function extractDesiredAttributes (array $desiredStatus): array + { + return [ + 'resource' => $desiredStatus[0]['fdarchivetaskresource'][0] ?? NULL, + 'state' => $desiredStatus[0]['fdarchivetaskstate'][0] ?? NULL, + 'substate' => $desiredStatus[0]['fdarchivetasksubstate'][0] ?? NULL, + ]; + } + + private function doesResourceMatch (string $resource, array $desiredAttributes): bool + { + // Extract parts from the resource string + $parts = explode(':', $resource); + $resourcePart = str_replace(['{', '}'], '', $parts[0]); + $substatePart = $parts[1] ?? ''; + + $resourceMatch = $resourcePart === $desiredAttributes['resource'] . $desiredAttributes['state']; + $substateMatch = empty($desiredAttributes['substate']) || $substatePart === $desiredAttributes['substate']; + + return $resourceMatch && $substateMatch; + } } \ No newline at end of file -- GitLab From 425afba0299bfcf18978efc9313e97bdbce2004e Mon Sep 17 00:00:00 2001 From: Thibault Dockx <thibault.dockx@fusiondirectory.org> Date: Mon, 31 Mar 2025 15:15:44 +0100 Subject: [PATCH 3/3] :art: refactor(archive) - update return type of getUserSupannAccountStatus method to ensure consistent array output --- plugins/tasks/Archive.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/tasks/Archive.php b/plugins/tasks/Archive.php index d4ace78..aa6932a 100644 --- a/plugins/tasks/Archive.php +++ b/plugins/tasks/Archive.php @@ -101,9 +101,9 @@ class Archive implements EndpointInterface /** * Retrieve the supannAccountStatus of a user * @param string $userDn - * @return array|null + * @return array */ - private function getUserSupannAccountStatus (string $userDn): ?array + private function getUserSupannAccountStatus (string $userDn): array { return $this->gateway->getLdapTasks( '(objectClass=supannPerson)', -- GitLab