• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LibreSign / libresign / 21268273482

22 Jan 2026 11:13PM UTC coverage: 45.185%. First build
21268273482

Pull #6526

github

web-flow
Merge 16c32ce29 into 068f2ad0f
Pull Request #6526: fix: progress cache factory

84 of 183 new or added lines in 6 files covered. (45.9%)

7348 of 16262 relevant lines covered (45.19%)

4.95 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/lib/Controller/FileProgressController.php
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\Controller;
10

11
use OCA\Libresign\AppInfo\Application;
12
use OCA\Libresign\Db\File as FileEntity;
13
use OCA\Libresign\Db\FileMapper;
14
use OCA\Libresign\Db\SignRequest as SignRequestEntity;
15
use OCA\Libresign\Db\SignRequestMapper;
16
use OCA\Libresign\Enum\FileStatus;
17
use OCA\Libresign\Middleware\Attribute\RequireSignerUuid;
18
use OCA\Libresign\Service\FileService;
19
use OCA\Libresign\Service\SessionService;
20
use OCA\Libresign\Service\SignRequest\ProgressService;
21
use OCA\Libresign\Service\WorkerHealthService;
22
use OCP\AppFramework\Http;
23
use OCP\AppFramework\Http\Attribute\ApiRoute;
24
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
25
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
26
use OCP\AppFramework\Http\Attribute\PublicPage;
27
use OCP\AppFramework\Http\DataResponse;
28
use OCP\IRequest;
29
use OCP\IUserSession;
30

31
/**
32
 * @psalm-import-type LibresignValidateFile from \OCA\Libresign\ResponseDefinitions
33
 */
34
class FileProgressController extends AEnvironmentAwareController {
35
        public function __construct(
36
                IRequest $request,
37
                private FileMapper $fileMapper,
38
                private SignRequestMapper $signRequestMapper,
39
                private FileService $fileService,
40
                private SessionService $sessionService,
41
                private IUserSession $userSession,
42
                private WorkerHealthService $workerHealthService,
43
                private ProgressService $progressService,
44
        ) {
NEW
45
                parent::__construct(Application::APP_ID, $request);
×
46
        }
47

48
        /**
49
         * Check file progress by sign request UUID with long-polling (similar to Talk)
50
         *
51
         * Waits up to 30 seconds for status change using cache for efficiency.
52
         * Returns progress for the specific sign request, not the global file status.
53
         *
54
         * @param string $uuid Sign request UUID
55
         * @param int $timeout Maximum seconds to wait (default 30)
56
         * @return DataResponse<Http::STATUS_OK, array{status: string, statusCode: int, statusText: string, fileId: int, progress: array<string, mixed>, file?: LibresignValidateFile}, array{}>|DataResponse<Http::STATUS_NOT_FOUND, array{message: string, status: string}, array{}>
57
         *
58
         * 200: Status and progress returned
59
         * 404: Sign request not found
60
         */
61
        #[NoAdminRequired]
62
        #[NoCSRFRequired]
63
        #[RequireSignerUuid]
64
        #[PublicPage]
65
        #[ApiRoute(verb: 'GET', url: '/api/{apiVersion}/file/progress/{uuid}', requirements: ['apiVersion' => '(v1)'])]
66
        public function checkProgressByUuid(string $uuid, int $timeout = 30): DataResponse {
67
                try {
NEW
68
                        $signRequest = $this->signRequestMapper->getByUuid($uuid);
×
NEW
69
                        $file = $this->fileMapper->getById($signRequest->getFileId());
×
NEW
70
                        $currentStatus = $this->progressService->getStatusCodeForSignRequest($file, $signRequest);
×
71

NEW
72
                        if ($file->getStatus() === FileStatus::SIGNING_IN_PROGRESS->value) {
×
73
                                $this->workerHealthService->ensureWorkerRunning();
×
NEW
74
                                $currentStatus = $this->progressService->pollForStatusChange($uuid, $currentStatus, $timeout);
×
75
                        }
76

NEW
77
                        return $this->buildStatusResponse($file, $signRequest, $currentStatus);
×
78

79
                } catch (\Exception $e) {
×
80
                        return new DataResponse([
×
81
                                'message' => $e->getMessage(),
×
82
                                'status' => 'ERROR',
×
83
                        ], Http::STATUS_NOT_FOUND);
×
84
                }
85
        }
86

87
        /**
88
         * Build HTTP response with status and progress information
89
         *
90
         * @param FileEntity $file The file entity
91
         * @param SignRequestEntity $signRequest The sign request entity
92
         * @param int $status Current status code
93
         * @return DataResponse<Http::STATUS_OK, array{status: string, statusCode: int, statusText: string, fileId: int, progress: array<string, mixed>, file?: LibresignValidateFile}, array{}>
94
         * @psalm-return DataResponse<Http::STATUS_OK, array{status: string, statusCode: int, statusText: string, fileId: int, progress: array<string, mixed>, file?: LibresignValidateFile}, array{}>
95
         */
96
        private function buildStatusResponse(FileEntity $file, SignRequestEntity $signRequest, int $status): DataResponse {
97
                $statusEnum = FileStatus::tryFrom($status);
×
NEW
98
                $progress = $this->progressService->getSignRequestProgress($file, $signRequest);
×
NEW
99
                $response = [
×
100
                        'status' => $statusEnum?->name ?? 'UNKNOWN',
×
101
                        'statusCode' => $status,
×
102
                        'statusText' => $this->fileMapper->getTextOfStatus($status),
×
103
                        'fileId' => $file->getId(),
×
NEW
104
                        'progress' => $progress,
×
105
                ];
×
106

NEW
107
                if ($this->progressService->isProgressComplete($progress)) {
×
NEW
108
                        $response['file'] = $this->fileService
×
NEW
109
                                ->setFile($file)
×
NEW
110
                                ->setSignRequest($signRequest)
×
NEW
111
                                ->setIdentifyMethodId($this->sessionService->getIdentifyMethodId())
×
NEW
112
                                ->setHost($this->request->getServerHost())
×
NEW
113
                                ->setMe($this->userSession->getUser())
×
NEW
114
                                ->showVisibleElements()
×
NEW
115
                                ->showSigners()
×
NEW
116
                                ->showSettings()
×
NEW
117
                                ->showMessages()
×
NEW
118
                                ->showValidateFile()
×
NEW
119
                                ->toArray();
×
120
                }
121

NEW
122
                return new DataResponse($response, Http::STATUS_OK);
×
123
        }
124
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc