Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
96.30% |
26 / 27 |
|
50.00% |
1 / 2 |
CRAP | |
0.00% |
0 / 1 |
| NotificationDeliveryStatusService | |
96.30% |
26 / 27 |
|
50.00% |
1 / 2 |
12 | |
0.00% |
0 / 1 |
| __construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| status | |
96.15% |
25 / 26 |
|
0.00% |
0 / 1 |
11 | |||
| 1 | <?php |
| 2 | |
| 3 | declare(strict_types=1); |
| 4 | /** |
| 5 | * SPDX-FileCopyrightText: 2026 LibreCode coop and contributors |
| 6 | * SPDX-License-Identifier: AGPL-3.0-or-later |
| 7 | */ |
| 8 | |
| 9 | namespace OCA\Libresign\Service\Notification; |
| 10 | |
| 11 | use OCA\Libresign\Db\NotificationDeliveryMapper; |
| 12 | use OCA\Libresign\Db\SignRequestMapper; |
| 13 | use OCA\Libresign\Enum\NotificationDeliveryState; |
| 14 | use OCA\Libresign\Exception\LibresignException; |
| 15 | use OCA\Libresign\Service\Validation\FileInputValidator; |
| 16 | use OCA\Libresign\Service\Validation\SigningRequestValidator; |
| 17 | use OCP\IUserSession; |
| 18 | |
| 19 | /** |
| 20 | * Read the state of one manual notification event. |
| 21 | * |
| 22 | * No recipient, message body, event key or provider error is returned. |
| 23 | * Authorization is checked before any delivery record is read. |
| 24 | */ |
| 25 | class NotificationDeliveryStatusService { |
| 26 | public function __construct( |
| 27 | private SigningRequestValidator $validator, |
| 28 | private FileInputValidator $fileInputValidator, |
| 29 | private IUserSession $userSession, |
| 30 | private SignRequestMapper $signRequests, |
| 31 | private NotificationDeliveryMapper $deliveries, |
| 32 | private NotificationDeliveryKeyFactory $keys, |
| 33 | ) { |
| 34 | } |
| 35 | |
| 36 | /** @return array{status: string, complete: bool, channels: list<array{channel: string, state: string}>} */ |
| 37 | public function status(int $fileId, int $signRequestId, string $requestId): array { |
| 38 | $this->validator->canRequestSign($this->userSession->getUser()); |
| 39 | $this->fileInputValidator->validateLibreSignFileId($fileId); |
| 40 | $this->validator->iRequestedSignThisFile($this->userSession->getUser(), $fileId); |
| 41 | $this->signRequests->getByFileIdAndSignRequestId($fileId, $signRequestId); |
| 42 | if (!preg_match('/\A[a-f0-9]{32}\z/D', $requestId)) { |
| 43 | throw new LibresignException('Invalid notification request ID'); |
| 44 | } |
| 45 | |
| 46 | $correlationId = $this->keys->correlationId('manual:' . $requestId, 'sign_request', $fileId, $signRequestId); |
| 47 | $channels = []; |
| 48 | $processing = false; |
| 49 | $attention = false; |
| 50 | foreach ($this->deliveries->findForEvent($correlationId) as $delivery) { |
| 51 | if ($delivery->getFileId() !== $fileId |
| 52 | || $delivery->getSignRequestId() !== $signRequestId |
| 53 | || $delivery->getEventType() !== 'sign_request') { |
| 54 | continue; |
| 55 | } |
| 56 | $state = $delivery->getState(); |
| 57 | $channels[] = ['channel' => $delivery->getChannel(), 'state' => $state]; |
| 58 | if (in_array($state, [NotificationDeliveryState::PENDING->value, NotificationDeliveryState::SENDING->value], true)) { |
| 59 | $processing = true; |
| 60 | } elseif ($state !== NotificationDeliveryState::ACCEPTED->value) { |
| 61 | $attention = true; |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | return [ |
| 66 | 'status' => $processing ? 'processing' : ($attention ? 'attention_required' : ($channels === [] ? 'not_found' : 'completed')), |
| 67 | 'complete' => !$processing, |
| 68 | 'channels' => $channels, |
| 69 | ]; |
| 70 | } |
| 71 | } |