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

LibreSign / libresign / 19875332299

02 Dec 2025 10:16PM UTC coverage: 41.686%. First build
19875332299

Pull #4464

github

web-flow
Merge b1d57ae77 into da0973853
Pull Request #4464: refactor: attach document

113 of 256 new or added lines in 15 files covered. (44.14%)

5122 of 12287 relevant lines covered (41.69%)

4.18 hits per line

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

0.0
/lib/Controller/PageController.php
1
<?php
2

3
declare(strict_types=1);
4
/**
5
 * SPDX-FileCopyrightText: 2020-2024 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\Exception\LibresignException;
13
use OCA\Libresign\Helper\JSActions;
14
use OCA\Libresign\Helper\ValidateHelper;
15
use OCA\Libresign\Middleware\Attribute\PrivateValidation;
16
use OCA\Libresign\Middleware\Attribute\RequireSetupOk;
17
use OCA\Libresign\Middleware\Attribute\RequireSignRequestUuid;
18
use OCA\Libresign\Service\AccountService;
19
use OCA\Libresign\Service\FileService;
20
use OCA\Libresign\Service\IdentifyMethod\SignatureMethod\TokenService;
21
use OCA\Libresign\Service\IdentifyMethodService;
22
use OCA\Libresign\Service\RequestSignatureService;
23
use OCA\Libresign\Service\SessionService;
24
use OCA\Libresign\Service\SignerElementsService;
25
use OCA\Libresign\Service\SignFileService;
26
use OCA\Viewer\Event\LoadViewer;
27
use OCP\AppFramework\Db\DoesNotExistException;
28
use OCP\AppFramework\Http;
29
use OCP\AppFramework\Http\Attribute\AnonRateLimit;
30
use OCP\AppFramework\Http\Attribute\FrontpageRoute;
31
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
32
use OCP\AppFramework\Http\Attribute\NoCSRFRequired;
33
use OCP\AppFramework\Http\Attribute\PublicPage;
34
use OCP\AppFramework\Http\ContentSecurityPolicy;
35
use OCP\AppFramework\Http\DataResponse;
36
use OCP\AppFramework\Http\FileDisplayResponse;
37
use OCP\AppFramework\Http\TemplateResponse;
38
use OCP\AppFramework\Services\IInitialState;
39
use OCP\EventDispatcher\IEventDispatcher;
40
use OCP\IAppConfig;
41
use OCP\IL10N;
42
use OCP\IRequest;
43
use OCP\IURLGenerator;
44
use OCP\IUserSession;
45
use OCP\Util;
46

47
class PageController extends AEnvironmentPageAwareController {
48
        public function __construct(
49
                IRequest $request,
50
                protected IUserSession $userSession,
51
                private SessionService $sessionService,
52
                private IInitialState $initialState,
53
                private AccountService $accountService,
54
                protected SignFileService $signFileService,
55
                protected RequestSignatureService $requestSignatureService,
56
                private SignerElementsService $signerElementsService,
57
                protected IL10N $l10n,
58
                private IdentifyMethodService $identifyMethodService,
59
                private IAppConfig $appConfig,
60
                private FileService $fileService,
61
                private ValidateHelper $validateHelper,
62
                private IEventDispatcher $eventDispatcher,
63
                private IURLGenerator $urlGenerator,
64
        ) {
65
                parent::__construct(
×
66
                        request: $request,
×
67
                        signFileService: $signFileService,
×
68
                        l10n: $l10n,
×
69
                        userSession: $userSession,
×
70
                );
×
71
        }
72

73
        /**
74
         * Index page
75
         *
76
         * @return TemplateResponse<Http::STATUS_OK, array{}>
77
         *
78
         * 200: OK
79
         */
80
        #[NoAdminRequired]
81
        #[NoCSRFRequired]
82
        #[RequireSetupOk(template: 'main')]
83
        #[FrontpageRoute(verb: 'GET', url: '/')]
84
        public function index(): TemplateResponse {
85
                $this->initialState->provideInitialState('config', $this->accountService->getConfig($this->userSession->getUser()));
×
86
                $this->initialState->provideInitialState('certificate_engine', $this->accountService->getCertificateEngineName());
×
87

88
                try {
89
                        $this->validateHelper->canRequestSign($this->userSession->getUser());
×
90
                        $this->initialState->provideInitialState('can_request_sign', true);
×
91
                } catch (LibresignException) {
×
92
                        $this->initialState->provideInitialState('can_request_sign', false);
×
93
                }
94

95
                $this->provideSignerSignatues();
×
96
                $this->initialState->provideInitialState('identify_methods', $this->identifyMethodService->getIdentifyMethodsSettings());
×
97
                $this->initialState->provideInitialState('legal_information', $this->appConfig->getValueString(Application::APP_ID, 'legal_information'));
×
98

99
                Util::addScript(Application::APP_ID, 'libresign-main');
×
100

101
                if (class_exists(LoadViewer::class)) {
×
102
                        $this->eventDispatcher->dispatchTyped(new LoadViewer());
×
103
                }
104

105
                $response = new TemplateResponse(Application::APP_ID, 'main');
×
106

107
                $policy = new ContentSecurityPolicy();
×
108
                $policy->allowEvalScript(true);
×
109
                $policy->addAllowedFrameDomain('\'self\'');
×
110
                $response->setContentSecurityPolicy($policy);
×
111

112
                return $response;
×
113
        }
114

115
        /**
116
         * Index page to authenticated users
117
         *
118
         * This router is used to be possible render pages with /f/, is a
119
         * workaround at frontend side to identify pages with authenticated accounts
120
         *
121
         * @return TemplateResponse<Http::STATUS_OK, array{}>
122
         *
123
         * 200: OK
124
         */
125
        #[NoAdminRequired]
126
        #[NoCSRFRequired]
127
        #[RequireSetupOk(template: 'main')]
128
        #[FrontpageRoute(verb: 'GET', url: '/f/')]
129
        public function indexF(): TemplateResponse {
130
                return $this->index();
×
131
        }
132

133
        /**
134
         * Incomplete page
135
         *
136
         * @return TemplateResponse<Http::STATUS_OK, array{}>
137
         *
138
         * 200: OK
139
         */
140
        #[NoAdminRequired]
141
        #[NoCSRFRequired]
142
        #[FrontpageRoute(verb: 'GET', url: '/f/incomplete')]
143
        public function incomplete(): TemplateResponse {
144
                Util::addScript(Application::APP_ID, 'libresign-main');
×
145
                $response = new TemplateResponse(Application::APP_ID, 'main');
×
146
                return $response;
×
147
        }
148

149
        /**
150
         * Incomplete page in full screen
151
         *
152
         * @return TemplateResponse<Http::STATUS_OK, array{}>
153
         *
154
         * 200: OK
155
         */
156
        #[PublicPage]
157
        #[NoCSRFRequired]
158
        #[FrontpageRoute(verb: 'GET', url: '/p/incomplete')]
159
        public function incompleteP(): TemplateResponse {
160
                Util::addScript(Application::APP_ID, 'libresign-main');
×
161
                $response = new TemplateResponse(Application::APP_ID, 'main', [], TemplateResponse::RENDER_AS_BASE);
×
162
                return $response;
×
163
        }
164

165
        /**
166
         * Main page to authenticated signer with a path
167
         *
168
         * The path is used only by frontend
169
         *
170
         * @param string $path The path that was sent from frontend
171
         * @return TemplateResponse<Http::STATUS_OK, array{}>
172
         *
173
         * 200: OK
174
         */
175
        #[NoAdminRequired]
176
        #[NoCSRFRequired]
177
        #[RequireSetupOk(template: 'main')]
178
        #[FrontpageRoute(verb: 'GET', url: '/f/{path}', requirements: ['path' => '.+'])]
179
        public function indexFPath(string $path): TemplateResponse {
180
                if (preg_match('/validation\/(?<uuid>[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12})$/', $path, $matches)) {
×
181

182
                        try {
183
                                $this->initialState->provideInitialState('file_info',
×
184
                                        $this->fileService
×
185
                                                ->setFileByType('uuid', $matches['uuid'])
×
186
                                                ->setIdentifyMethodId($this->sessionService->getIdentifyMethodId())
×
187
                                                ->setHost($this->request->getServerHost())
×
188
                                                ->setMe($this->userSession->getUser())
×
189
                                                ->showVisibleElements()
×
190
                                                ->showSigners()
×
191
                                                ->showSettings()
×
192
                                                ->showMessages()
×
193
                                                ->showValidateFile()
×
194
                                                ->toArray()
×
195
                                );
×
196
                        } catch (LibresignException) {
×
197
                                throw new LibresignException(json_encode([
×
198
                                        'action' => JSActions::ACTION_DO_NOTHING,
×
199
                                        'errors' => [['message' => $this->l10n->t('Invalid UUID')]],
×
200
                                ]), Http::STATUS_NOT_FOUND);
×
201
                        }
202
                }
203
                return $this->index();
×
204
        }
205

206

207
        /**
208
         * Sign page to authenticated signer
209
         *
210
         * @param string $uuid Sign request uuid
211
         * @return TemplateResponse<Http::STATUS_OK, array{}>
212
         *
213
         * 200: OK
214
         */
215
        #[NoAdminRequired]
216
        #[NoCSRFRequired]
217
        #[RequireSetupOk]
218
        #[PublicPage]
219
        #[RequireSignRequestUuid]
220
        #[FrontpageRoute(verb: 'GET', url: '/f/sign/{uuid}')]
221
        public function signF(string $uuid): TemplateResponse {
222
                $this->initialState->provideInitialState('action', JSActions::ACTION_SIGN_INTERNAL);
×
223
                return $this->index();
×
224
        }
225

226
        /**
227
         * Sign page to authenticated signer with the path of file
228
         *
229
         * The path is used only by frontend
230
         *
231
         * @param string $uuid Sign request uuid
232
         * @return TemplateResponse<Http::STATUS_OK, array{}>
233
         *
234
         * 200: OK
235
         */
236
        #[NoAdminRequired]
237
        #[NoCSRFRequired]
238
        #[RequireSetupOk]
239
        #[PublicPage]
240
        #[RequireSignRequestUuid]
241
        #[FrontpageRoute(verb: 'GET', url: '/f/sign/{uuid}/{path}', requirements: ['path' => '.+'])]
242
        public function signFPath(string $uuid): TemplateResponse {
243
                $this->initialState->provideInitialState('action', JSActions::ACTION_SIGN_INTERNAL);
×
244
                return $this->index();
×
245
        }
246

247
        /**
248
         * Sign page to unauthenticated signer
249
         *
250
         * The path is used only by frontend
251
         *
252
         * @param string $uuid Sign request uuid
253
         * @return TemplateResponse<Http::STATUS_OK, array{}>
254
         *
255
         * 200: OK
256
         */
257
        #[NoAdminRequired]
258
        #[NoCSRFRequired]
259
        #[RequireSetupOk]
260
        #[PublicPage]
261
        #[RequireSignRequestUuid]
262
        #[FrontpageRoute(verb: 'GET', url: '/p/sign/{uuid}/{path}', requirements: ['path' => '.+'])]
263
        public function signPPath(string $uuid): TemplateResponse {
264
                return $this->sign($uuid);
×
265
        }
266

267
        /**
268
         * Sign page to unauthenticated signer
269
         *
270
         * The path is used only by frontend
271
         *
272
         * @param string $uuid Sign request uuid
273
         * @return TemplateResponse<Http::STATUS_OK, array{}>
274
         *
275
         * 200: OK
276
         */
277
        #[PrivateValidation]
278
        #[NoAdminRequired]
279
        #[NoCSRFRequired]
280
        #[RequireSetupOk]
281
        #[PublicPage]
282
        #[RequireSignRequestUuid]
283
        #[FrontpageRoute(verb: 'GET', url: '/p/sign/{uuid}')]
284
        public function sign(string $uuid): TemplateResponse {
285
                $this->initialState->provideInitialState('action', JSActions::ACTION_SIGN);
×
286
                $this->initialState->provideInitialState('config',
×
287
                        $this->accountService->getConfig($this->userSession->getUser())
×
288
                );
×
289
                $this->initialState->provideInitialState('filename', $this->getFileEntity()->getName());
×
290
                $file = $this->fileService
×
291
                        ->setFile($this->getFileEntity())
×
292
                        ->setHost($this->request->getServerHost())
×
293
                        ->setMe($this->userSession->getUser())
×
NEW
294
                        ->setSignerIdentified()
×
295
                        ->setIdentifyMethodId($this->sessionService->getIdentifyMethodId())
×
296
                        ->setSignRequest($this->getSignRequestEntity())
×
297
                        ->showVisibleElements()
×
298
                        ->showSigners()
×
NEW
299
                        ->showSettings()
×
300
                        ->toArray();
×
NEW
301
                $this->initialState->provideInitialState('config', [
×
NEW
302
                        'identificationDocumentsFlow' => $file['settings']['needIdentificationDocuments'] ?? false,
×
NEW
303
                ]);
×
NEW
304
                $this->initialState->provideInitialState('needIdentificationDocuments', $file['settings']['needIdentificationDocuments'] ?? false);
×
NEW
305
                $this->initialState->provideInitialState('identificationDocumentsWaitingApproval', $file['settings']['identificationDocumentsWaitingApproval'] ?? false);
×
306
                $this->initialState->provideInitialState('status', $file['status']);
×
307
                $this->initialState->provideInitialState('statusText', $file['statusText']);
×
308
                $this->initialState->provideInitialState('signers', $file['signers']);
×
309
                $this->initialState->provideInitialState('sign_request_uuid', $uuid);
×
310
                $this->provideSignerSignatues();
×
311
                $this->initialState->provideInitialState('token_length', TokenService::TOKEN_LENGTH);
×
312
                $this->initialState->provideInitialState('description', $this->getSignRequestEntity()->getDescription() ?? '');
×
313
                $this->initialState->provideInitialState('pdf',
×
314
                        $this->signFileService->getFileUrl('url', $this->getFileEntity(), $this->getNextcloudFile(), $uuid)
×
315
                );
×
316
                $this->initialState->provideInitialState('nodeId', $this->getFileEntity()->getNodeId());
×
317

318
                Util::addScript(Application::APP_ID, 'libresign-external');
×
319
                $response = new TemplateResponse(Application::APP_ID, 'external', [], TemplateResponse::RENDER_AS_BASE);
×
320

321
                $policy = new ContentSecurityPolicy();
×
322
                $policy->allowEvalScript(true);
×
323
                $response->setContentSecurityPolicy($policy);
×
324

325
                return $response;
×
326
        }
327

328
        private function provideSignerSignatues(): void {
329
                $signatures = [];
×
330
                if ($this->userSession->getUser()) {
×
331
                        $signatures = $this->signerElementsService->getUserElements($this->userSession->getUser()->getUID());
×
332
                } else {
333
                        $signatures = $this->signerElementsService->getElementsFromSessionAsArray();
×
334
                }
335
                $this->initialState->provideInitialState('user_signatures', $signatures);
×
336
        }
337

338
        /**
339
         * Show signature page
340
         *
341
         * @param string $uuid Sign request uuid
342
         * @return TemplateResponse<Http::STATUS_OK, array{}>
343
         *
344
         * 200: OK
345
         * 404: Invalid UUID
346
         */
347
        #[NoAdminRequired]
348
        #[NoCSRFRequired]
349
        #[RequireSetupOk]
350
        #[FrontpageRoute(verb: 'GET', url: '/p/id-docs/approve/{uuid}')]
351
        #[FrontpageRoute(verb: 'GET', url: '/p/id-docs/approve/{uuid}/{path}', requirements: ['path' => '.+'], postfix: 'private')]
352
        public function signIdDoc($uuid): TemplateResponse {
353
                try {
354
                        $fileEntity = $this->signFileService->getFileByUuid($uuid);
×
NEW
355
                        $this->signFileService->getIdDocById($fileEntity->getId());
×
356
                } catch (DoesNotExistException) {
×
357
                        throw new LibresignException(json_encode([
×
358
                                'action' => JSActions::ACTION_DO_NOTHING,
×
359
                                'errors' => [['message' => $this->l10n->t('Invalid UUID')]],
×
360
                        ]), Http::STATUS_NOT_FOUND);
×
361
                }
NEW
362
                $this->initialState->provideInitialState('action', JSActions::ACTION_SIGN_ID_DOC);
×
363
                $this->initialState->provideInitialState('config',
×
364
                        $this->accountService->getConfig($this->userSession->getUser())
×
365
                );
×
366
                $this->initialState->provideInitialState('signer',
×
367
                        $this->signFileService->getSignerData(
×
368
                                $this->userSession->getUser(),
×
369
                        )
×
370
                );
×
371
                $this->initialState->provideInitialState('identifyMethods',
×
372
                        $this->signFileService->getAvailableIdentifyMethodsFromSettings()
×
373
                );
×
374
                $this->initialState->provideInitialState('filename', $fileEntity->getName());
×
375
                $file = $this->fileService
×
376
                        ->setFile($fileEntity)
×
377
                        ->setHost($this->request->getServerHost())
×
378
                        ->setMe($this->userSession->getUser())
×
379
                        ->setIdentifyMethodId($this->sessionService->getIdentifyMethodId())
×
380
                        ->showVisibleElements()
×
381
                        ->showSigners()
×
382
                        ->toArray();
×
383
                $this->initialState->provideInitialState('fileId', $file['nodeId']);
×
384
                $this->initialState->provideInitialState('status', $file['status']);
×
385
                $this->initialState->provideInitialState('statusText', $file['statusText']);
×
386
                $this->initialState->provideInitialState('visibleElements', []);
×
387
                $this->initialState->provideInitialState('signers', []);
×
388
                $this->provideSignerSignatues();
×
389
                $signatureMethods = $this->identifyMethodService->getSignMethodsOfIdentifiedFactors($this->getSignRequestEntity()->getId());
×
390
                $this->initialState->provideInitialState('signature_methods', $signatureMethods);
×
391
                $this->initialState->provideInitialState('token_length', TokenService::TOKEN_LENGTH);
×
392
                $this->initialState->provideInitialState('description', '');
×
393
                $nextcloudFile = $this->signFileService->getNextcloudFile($fileEntity);
×
394
                $this->initialState->provideInitialState('pdf',
×
395
                        $this->signFileService->getFileUrl('url', $fileEntity, $nextcloudFile, $uuid)
×
396
                );
×
397

398
                Util::addScript(Application::APP_ID, 'libresign-external');
×
399
                $response = new TemplateResponse(Application::APP_ID, 'external', [], TemplateResponse::RENDER_AS_BASE);
×
400

401
                $policy = new ContentSecurityPolicy();
×
402
                $policy->allowEvalScript(true);
×
403
                $response->setContentSecurityPolicy($policy);
×
404

405
                return $response;
×
406
        }
407

408
        /**
409
         * Use UUID of file to get PDF
410
         *
411
         * @param string $uuid File uuid
412
         * @return FileDisplayResponse<Http::STATUS_OK, array{Content-Type: string}>|DataResponse<Http::STATUS_NOT_FOUND, array<empty>, array{}>
413
         *
414
         * 200: OK
415
         * 401: Validation page not accessible if unauthenticated
416
         * 404: File not found
417
         */
418
        #[PrivateValidation]
419
        #[NoAdminRequired]
420
        #[NoCSRFRequired]
421
        #[RequireSetupOk]
422
        #[PublicPage]
423
        #[AnonRateLimit(limit: 30, period: 60)]
424
        #[FrontpageRoute(verb: 'GET', url: '/p/pdf/{uuid}')]
425
        public function getPdf($uuid) {
426
                try {
427
                        $file = $this->accountService->getPdfByUuid($uuid);
×
428
                } catch (DoesNotExistException) {
×
429
                        return new DataResponse([], Http::STATUS_NOT_FOUND);
×
430
                }
431

432
                return new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => $file->getMimeType()]);
×
433
        }
434

435
        /**
436
         * Use UUID of user to get PDF
437
         *
438
         * @param string $uuid Sign request uuid
439
         * @return FileDisplayResponse<Http::STATUS_OK, array{Content-Type: string}>
440
         *
441
         * 200: OK
442
         * 401: Validation page not accessible if unauthenticated
443
         */
444
        #[PrivateValidation]
445
        #[NoAdminRequired]
446
        #[NoCSRFRequired]
447
        #[RequireSignRequestUuid]
448
        #[PublicPage]
449
        #[RequireSetupOk]
450
        #[AnonRateLimit(limit: 30, period: 60)]
451
        #[FrontpageRoute(verb: 'GET', url: '/pdf/{uuid}')]
452
        public function getPdfFile($uuid): FileDisplayResponse {
453
                $file = $this->getNextcloudFile();
×
454
                return new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => $file->getMimeType()]);
×
455
        }
456

457
        /**
458
         * Show validation page
459
         *
460
         * @return TemplateResponse<Http::STATUS_OK, array{}>
461
         *
462
         * 200: OK
463
         * 401: Validation page not accessible if unauthenticated
464
         */
465
        #[PrivateValidation]
466
        #[NoAdminRequired]
467
        #[NoCSRFRequired]
468
        #[RequireSetupOk(template: 'validation')]
469
        #[PublicPage]
470
        #[AnonRateLimit(limit: 30, period: 60)]
471
        #[FrontpageRoute(verb: 'GET', url: '/p/validation')]
472
        public function validation(): TemplateResponse {
473
                if ($this->getFileEntity()) {
×
474
                        $this->initialState->provideInitialState('config',
×
475
                                $this->accountService->getConfig($this->userSession->getUser())
×
476
                        );
×
477
                        $this->initialState->provideInitialState('file', [
×
478
                                'uuid' => $this->getFileEntity()?->getUuid(),
×
479
                                'description' => $this->getSignRequestEntity()?->getDescription(),
×
480
                        ]);
×
481
                        $this->initialState->provideInitialState('filename', $this->getFileEntity()?->getName());
×
482
                        $this->initialState->provideInitialState('pdf',
×
483
                                $this->signFileService->getFileUrl('url', $this->getFileEntity(), $this->getNextcloudFile(), $this->request->getParam('uuid'))
×
484
                        );
×
485
                        $this->initialState->provideInitialState('signer',
×
486
                                $this->signFileService->getSignerData(
×
487
                                        $this->userSession->getUser(),
×
488
                                        $this->getSignRequestEntity(),
×
489
                                )
×
490
                        );
×
491
                }
492

493
                Util::addScript(Application::APP_ID, 'libresign-validation');
×
494
                $response = new TemplateResponse(Application::APP_ID, 'validation', [], TemplateResponse::RENDER_AS_BASE);
×
495

496
                return $response;
×
497
        }
498

499
        /**
500
         * Show validation page
501
         *
502
         * The path is used only by frontend
503
         *
504
         * @param string $uuid Sign request uuid
505
         * @return TemplateResponse<Http::STATUS_OK, array{}>
506
         *
507
         * 200: OK
508
         * 303: Redirected to validation page
509
         * 401: Validation page not accessible if unauthenticated
510
         */
511
        #[PrivateValidation]
512
        #[NoAdminRequired]
513
        #[NoCSRFRequired]
514
        #[RequireSetupOk]
515
        #[PublicPage]
516
        #[AnonRateLimit(limit: 30, period: 60)]
517
        #[FrontpageRoute(verb: 'GET', url: '/validation/{uuid}')]
518
        public function validationFileWithShortUrl(): TemplateResponse {
519
                return $this->validationFilePublic($this->request->getParam('uuid'));
×
520
        }
521

522
        /**
523
         * Show validation page
524
         *
525
         * @param string $uuid Sign request uuid
526
         * @return TemplateResponse<Http::STATUS_OK, array{}>
527
         *
528
         * 200: OK
529
         */
530
        #[NoAdminRequired]
531
        #[NoCSRFRequired]
532
        #[RequireSetupOk(template: 'main')]
533
        #[PublicPage]
534
        #[RequireSignRequestUuid]
535
        #[FrontpageRoute(verb: 'GET', url: '/reset-password')]
536
        public function resetPassword(): TemplateResponse {
537
                $this->initialState->provideInitialState('config',
×
538
                        $this->accountService->getConfig($this->userSession->getUser())
×
539
                );
×
540

541
                Util::addScript(Application::APP_ID, 'libresign-main');
×
542
                $response = new TemplateResponse(Application::APP_ID, 'reset_password');
×
543

544
                return $response;
×
545
        }
546

547
        /**
548
         * Public page to show validation for a specific file UUID
549
         *
550
         * @param string $uuid File uuid
551
         * @return TemplateResponse<Http::STATUS_OK, array{}>
552
         *
553
         * 200: OK
554
         * 401: Validation page not accessible if unauthenticated
555
         */
556
        #[PrivateValidation]
557
        #[NoAdminRequired]
558
        #[NoCSRFRequired]
559
        #[RequireSetupOk(template: 'validation')]
560
        #[PublicPage]
561
        #[AnonRateLimit(limit: 30, period: 60)]
562
        #[FrontpageRoute(verb: 'GET', url: '/p/validation/{uuid}')]
563
        public function validationFilePublic(string $uuid): TemplateResponse {
564
                try {
565
                        $this->signFileService->getFileByUuid($uuid);
×
566
                        $this->fileService->setFileByType('uuid', $uuid);
×
567
                } catch (DoesNotExistException) {
×
568
                        try {
569
                                $signRequest = $this->signFileService->getSignRequestByUuid($uuid);
×
570
                                $libresignFile = $this->signFileService->getFile($signRequest->getFileId());
×
571
                                $this->fileService->setFile($libresignFile);
×
572
                        } catch (DoesNotExistException) {
×
573
                                $this->initialState->provideInitialState('action', JSActions::ACTION_DO_NOTHING);
×
574
                                $this->initialState->provideInitialState('errors', [['message' => $this->l10n->t('Invalid UUID')]]);
×
575
                        }
576
                }
577
                if ($this->userSession->isLoggedIn()) {
×
578
                        $this->initialState->provideInitialState('config',
×
579
                                $this->accountService->getConfig($this->userSession->getUser())
×
580
                        );
×
581
                        $this->fileService->setMe($this->userSession->getUser());
×
582
                } else {
583
                        $this->initialState->provideInitialState('config',
×
584
                                $this->accountService->getConfig()
×
585
                        );
×
586
                }
587

588
                $this->initialState->provideInitialState('legal_information', $this->appConfig->getValueString(Application::APP_ID, 'legal_information'));
×
589

590
                $this->initialState->provideInitialState('file_info',
×
591
                        $this->fileService
×
592
                                ->setIdentifyMethodId($this->sessionService->getIdentifyMethodId())
×
593
                                ->setHost($this->request->getServerHost())
×
594
                                ->showVisibleElements()
×
595
                                ->showSigners()
×
596
                                ->showSettings()
×
597
                                ->showMessages()
×
598
                                ->showValidateFile()
×
599
                                ->toArray()
×
600
                );
×
601

602
                Util::addScript(Application::APP_ID, 'libresign-validation');
×
603
                if (class_exists(LoadViewer::class)) {
×
604
                        $this->eventDispatcher->dispatchTyped(new LoadViewer());
×
605
                }
606
                $response = new TemplateResponse(Application::APP_ID, 'validation', [], TemplateResponse::RENDER_AS_BASE);
×
607

608
                return $response;
×
609
        }
610
}
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