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

LibreSign / libresign / 22009395141

14 Feb 2026 02:20AM UTC coverage: 51.545%. First build
22009395141

Pull #6888

github

web-flow
Merge 163408ef6 into 9d2660a39
Pull Request #6888: refactor: files list config prefixes

0 of 8 new or added lines in 1 file covered. (0.0%)

9058 of 17573 relevant lines covered (51.54%)

6.12 hits per line

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

25.27
/lib/Service/AccountService.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\Service;
10

11
use InvalidArgumentException;
12
use OCA\Libresign\AppInfo\Application;
13
use OCA\Libresign\Db\FileMapper;
14
use OCA\Libresign\Db\FileTypeMapper;
15
use OCA\Libresign\Db\IdentifyMethodMapper;
16
use OCA\Libresign\Db\SignRequest;
17
use OCA\Libresign\Db\SignRequestMapper;
18
use OCA\Libresign\Db\UserElement;
19
use OCA\Libresign\Db\UserElementMapper;
20
use OCA\Libresign\Enum\FileStatus;
21
use OCA\Libresign\Exception\InvalidPasswordException;
22
use OCA\Libresign\Exception\LibresignException;
23
use OCA\Libresign\Handler\CertificateEngine\CertificateEngineFactory;
24
use OCA\Libresign\Handler\SignEngine\Pkcs12Handler;
25
use OCA\Libresign\Helper\FileUploadHelper;
26
use OCA\Libresign\Helper\ValidateHelper;
27
use OCA\Settings\Mailer\NewUserMailHelper;
28
use OCP\Accounts\IAccountManager;
29
use OCP\AppFramework\Db\DoesNotExistException;
30
use OCP\AppFramework\Utility\ITimeFactory;
31
use OCP\Files\Config\IMountProviderCollection;
32
use OCP\Files\File;
33
use OCP\Files\IMimeTypeDetector;
34
use OCP\Files\IRootFolder;
35
use OCP\Files\NotFoundException;
36
use OCP\Http\Client\IClientService;
37
use OCP\IAppConfig;
38
use OCP\IConfig;
39
use OCP\IGroupManager;
40
use OCP\IL10N;
41
use OCP\IURLGenerator;
42
use OCP\IUser;
43
use OCP\IUserManager;
44
use Sabre\DAV\UUIDUtil;
45
use Throwable;
46

47
class AccountService {
48
        private ?SignRequest $signRequest = null;
49
        private ?\OCA\Libresign\Db\File $fileData = null;
50
        private \OCP\Files\File $fileToSign;
51

52
        public function __construct(
53
                private IL10N $l10n,
54
                private SignRequestMapper $signRequestMapper,
55
                private IUserManager $userManager,
56
                private IAccountManager $accountManager,
57
                private IRootFolder $root,
58
                private IMimeTypeDetector $mimeTypeDetector,
59
                private FileMapper $fileMapper,
60
                private FileTypeMapper $fileTypeMapper,
61
                private SignFileService $signFileService,
62
                private RequestSignatureService $requestSignatureService,
63
                private CertificateEngineFactory $certificateEngineFactory,
64
                private IConfig $config,
65
                private IAppConfig $appConfig,
66
                private IMountProviderCollection $mountProviderCollection,
67
                private NewUserMailHelper $newUserMail,
68
                private IdentifyMethodService $identifyMethodService,
69
                private IdentifyMethodMapper $identifyMethodMapper,
70
                private ValidateHelper $validateHelper,
71
                private IURLGenerator $urlGenerator,
72
                private Pkcs12Handler $pkcs12Handler,
73
                private IGroupManager $groupManager,
74
                private IdDocsService $idDocsService,
75
                private SignerElementsService $signerElementsService,
76
                private UserElementMapper $userElementMapper,
77
                private FolderService $folderService,
78
                private IClientService $clientService,
79
                private ITimeFactory $timeFactory,
80
                private FileUploadHelper $uploadHelper,
81
        ) {
82
        }
49✔
83

84
        public function validateCreateToSign(array $data): void {
85
                if (!UUIDUtil::validateUUID($data['uuid'])) {
1✔
86
                        throw new LibresignException($this->l10n->t('Invalid UUID'), 1);
1✔
87
                }
88
                try {
89
                        $signRequest = $this->getSignRequestByUuid($data['uuid']);
×
90
                } catch (\Throwable) {
×
91
                        throw new LibresignException($this->l10n->t('UUID not found'), 1);
×
92
                }
93
                $identifyMethods = $this->identifyMethodService->getIdentifyMethodsFromSignRequestId($signRequest->getId());
×
94
                if (!array_key_exists('identify', $data['user'])) {
×
95
                        throw new LibresignException($this->l10n->t('Invalid identification method'), 1);
×
96
                }
97
                foreach ($data['user']['identify'] as $method => $value) {
×
98
                        if (!array_key_exists($method, $identifyMethods)) {
×
99
                                throw new LibresignException($this->l10n->t('Invalid identification method'), 1);
×
100
                        }
101
                        foreach ($identifyMethods[$method] as $identifyMethod) {
×
102
                                $identifyMethod->validateToCreateAccount($value);
×
103
                        }
104
                }
105
                if (empty($data['password'])) {
×
106
                        throw new LibresignException($this->l10n->t('Password is mandatory'), 1);
×
107
                }
108
                $file = $this->getFileByUuid($data['uuid']);
×
109
                if (empty($file['fileToSign'])) {
×
110
                        throw new LibresignException($this->l10n->t('File not found'));
×
111
                }
112
        }
113

114
        public function getFileByUuid(string $uuid): array {
115
                $signRequest = $this->getSignRequestByUuid($uuid);
×
116
                if (!$this->fileData instanceof \OCA\Libresign\Db\File) {
×
117
                        $this->fileData = $this->fileMapper->getById($signRequest->getFileId());
×
118

119
                        $nodeId = $this->fileData->getNodeId();
×
120

121
                        $fileToSign = $this->root->getUserFolder($this->fileData->getUserId())->getFirstNodeById($nodeId);
×
122
                        if ($fileToSign) {
×
123
                                $this->fileToSign = $fileToSign;
×
124
                        }
125
                }
126
                return [
×
127
                        'fileData' => $this->fileData,
×
128
                        'fileToSign' => $this->fileToSign
×
129
                ];
×
130
        }
131

132
        public function validateCertificateData(array $data): void {
133
                if (array_key_exists('email', $data['user']) && empty($data['user']['email'])) {
7✔
134
                        throw new LibresignException($this->l10n->t('You must have an email. You can define the email in your profile.'), 1);
2✔
135
                }
136
                if (!empty($data['user']['email']) && !filter_var($data['user']['email'], FILTER_VALIDATE_EMAIL)) {
5✔
137
                        throw new LibresignException($this->l10n->t('Invalid email'), 1);
2✔
138
                }
139
                if (empty($data['signPassword'])) {
3✔
140
                        throw new LibresignException($this->l10n->t('Password to sign is mandatory'), 1);
1✔
141
                }
142
        }
143

144
        /**
145
         * Get signRequest by Uuid
146
         */
147
        public function getSignRequestByUuid(string $uuid): SignRequest {
148
                if (!$this->signRequest instanceof SignRequest) {
2✔
149
                        $this->signRequest = $this->signRequestMapper->getByUuid($uuid);
2✔
150
                }
151
                return $this->signRequest;
2✔
152
        }
153

154
        public function createToSign(string $uuid, string $email, string $password, ?string $signPassword): void {
155
                $signRequest = $this->getSignRequestByUuid($uuid);
2✔
156

157
                $newUser = $this->userManager->createUser($email, $password);
2✔
158
                $newUser->setDisplayName($signRequest->getDisplayName());
2✔
159
                $newUser->setSystemEMailAddress($email);
2✔
160

161
                $this->updateIdentifyMethodToAccount($signRequest->getId(), $email, $newUser->getUID());
2✔
162

163
                if ($this->config->getAppValue('core', 'newUser.sendEmail', 'yes') === 'yes') {
2✔
164
                        try {
165
                                $emailTemplate = $this->newUserMail->generateTemplate($newUser, false);
2✔
166
                                $this->newUserMail->sendMail($newUser, $emailTemplate);
2✔
167
                        } catch (\Exception) {
2✔
168
                                throw new LibresignException('Unable to send the invitation', 1);
2✔
169
                        }
170
                }
171

172
                if ($signPassword) {
×
173
                        $certificate = $this->pkcs12Handler->generateCertificate(
×
174
                                [
×
175
                                        'host' => $newUser->getPrimaryEMailAddress(),
×
176
                                        'uid' => 'account:' . $newUser->getUID(),
×
177
                                        'name' => $newUser->getDisplayName()
×
178
                                ],
×
179
                                $signPassword,
×
180
                                $newUser->getDisplayName()
×
181
                        );
×
182
                        $this->pkcs12Handler->savePfx($newUser->getPrimaryEMailAddress(), $certificate);
×
183
                }
184
        }
185

186
        public function getCertificateEngineName(): string {
187
                return $this->certificateEngineFactory->getEngine()->getName();
×
188
        }
189

190
        /**
191
         * @return array<string, mixed>
192
         */
193
        public function getConfig(?IUser $user = null): array {
194

195
                $info['identificationDocumentsFlow'] = $this->appConfig->getValueBool(Application::APP_ID, 'identification_documents', false);
×
196
                $info['hasSignatureFile'] = $this->hasSignatureFile($user);
×
197
                $info['phoneNumber'] = $this->getPhoneNumber($user);
×
198
                $info['isApprover'] = $this->validateHelper->userCanApproveValidationDocuments($user, false);
×
199
                $info['id_docs_filters'] = $this->getUserConfigIdDocsFilters($user);
×
200
                $info['id_docs_sort'] = $this->getUserConfigIdDocsSort($user);
×
201
                $info['crl_filters'] = $this->getUserConfigCrlFilters($user);
×
202
                $info['crl_sort'] = $this->getUserConfigCrlSort($user);
×
NEW
203
                $info['files_list_grid_view'] = $this->getUserConfigByKey('files_list_grid_view', $user) === '1';
×
NEW
204
                $info['files_list_signer_identify_tab'] = $this->getUserConfigByKey('files_list_signer_identify_tab', $user);
×
NEW
205
                $info['files_list_sorting_mode'] = $this->getUserConfigByKey('files_list_sorting_mode', $user) ?: 'name';
×
NEW
206
                $info['files_list_sorting_direction'] = $this->getUserConfigByKey('files_list_sorting_direction', $user) ?: 'asc';
×
207

208
                return array_filter($info);
×
209
        }
210

211
        public function getConfigFilters(?IUser $user = null): array {
NEW
212
                $info['files_list_filter_modified'] = $this->getUserConfigByKey('files_list_filter_modified', $user);
×
NEW
213
                $info['files_list_filter_status'] = $this->getUserConfigByKey('files_list_filter_status', $user);
×
214

215
                return $info;
×
216
        }
217

218
        public function getConfigSorting(?IUser $user = null): array {
NEW
219
                $info['files_list_sorting_mode'] = $this->getUserConfigByKey('files_list_sorting_mode', $user) ?: 'name';
×
NEW
220
                $info['files_list_sorting_direction'] = $this->getUserConfigByKey('files_list_sorting_direction', $user) ?: 'asc';
×
221

222
                return $info;
×
223
        }
224

225
        private function updateIdentifyMethodToAccount(int $signRequestId, string $email, string $uid): void {
226
                $identifyMethods = $this->identifyMethodService->getIdentifyMethodsFromSignRequestId($signRequestId);
2✔
227
                foreach ($identifyMethods as $name => $methods) {
2✔
228
                        if ($name === IdentifyMethodService::IDENTIFY_EMAIL) {
×
229
                                foreach ($methods as $identifyMethod) {
×
230
                                        $entity = $identifyMethod->getEntity();
×
231
                                        if ($entity->getIdentifierValue() === $email) {
×
232
                                                $entity->setIdentifierKey(IdentifyMethodService::IDENTIFY_ACCOUNT);
×
233
                                                $entity->setIdentifierValue($uid);
×
234
                                                $this->identifyMethodMapper->update($entity);
×
235
                                        }
236
                                }
237
                        }
238
                }
239
        }
240

241
        private function getPhoneNumber(?IUser $user): string {
242
                if (!$user) {
×
243
                        return '';
×
244
                }
245
                $userAccount = $this->accountManager->getAccount($user);
×
246
                return $userAccount->getProperty(IAccountManager::PROPERTY_PHONE)->getValue();
×
247
        }
248

249
        public function hasSignatureFile(?IUser $user = null): bool {
250
                if (!$user) {
1✔
251
                        return false;
×
252
                }
253
                try {
254
                        $this->pkcs12Handler->getPfxOfCurrentSigner($user->getUID());
1✔
255
                        return true;
×
256
                } catch (LibresignException) {
1✔
257
                        return false;
1✔
258
                }
259
        }
260

261
        private function getUserConfigByKey(string $key, ?IUser $user = null): string {
262
                if (!$user) {
×
263
                        return '';
×
264
                }
265

266
                return $this->config->getUserValue($user->getUID(), Application::APP_ID, $key);
×
267
        }
268

269
        private function getUserConfigIdDocsFilters(?IUser $user = null): array {
270
                if (!$user) {
×
271
                        return [];
×
272
                }
273

274
                $value = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'id_docs_filters', '');
×
275
                if (empty($value)) {
×
276
                        return [];
×
277
                }
278

279
                $decoded = json_decode($value, true);
×
280
                return is_array($decoded) ? $decoded : [];
×
281
        }
282

283
        private function getUserConfigCrlFilters(?IUser $user = null): array {
284
                if (!$user || !$this->groupManager->isAdmin($user->getUID())) {
×
285
                        return [];
×
286
                }
287

288
                $value = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'crl_filters', '');
×
289
                if (empty($value)) {
×
290
                        return [];
×
291
                }
292

293
                $decoded = json_decode($value, true);
×
294
                return is_array($decoded) ? $decoded : [];
×
295
        }
296

297
        private function getUserConfigCrlSort(?IUser $user): array {
298
                if (!$user || !$this->groupManager->isAdmin($user->getUID())) {
×
299
                        return ['sortBy' => 'revoked_at', 'sortOrder' => 'DESC'];
×
300
                }
301

302
                $value = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'crl_sort', '');
×
303
                if (empty($value)) {
×
304
                        return ['sortBy' => 'revoked_at', 'sortOrder' => 'DESC'];
×
305
                }
306

307
                $decoded = json_decode($value, true);
×
308
                return is_array($decoded) ? $decoded : ['sortBy' => 'revoked_at', 'sortOrder' => 'DESC'];
×
309
        }
310

311
        private function getUserConfigIdDocsSort(?IUser $user): array {
312
                if (!$user || !$this->validateHelper->userCanApproveValidationDocuments($user, false)) {
×
313
                        return ['sortBy' => null, 'sortOrder' => null];
×
314
                }
315

316
                $value = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'id_docs_sort', '');
×
317
                if (empty($value)) {
×
318
                        return ['sortBy' => null, 'sortOrder' => null];
×
319
                }
320

321
                $decoded = json_decode($value, true);
×
322
                return is_array($decoded) ? $decoded : ['sortBy' => null, 'sortOrder' => null];
×
323
        }
324

325
        /**
326
         * Get PDF node by UUID
327
         *
328
         * @psalm-suppress MixedReturnStatement
329
         * @throws Throwable
330
         * @return \OCP\Files\File
331
         */
332
        public function getPdfByUuid(string $uuid): File {
333
                $fileData = $this->fileMapper->getByUuid($uuid);
4✔
334

335
                if (in_array($fileData->getStatus(), [FileStatus::PARTIAL_SIGNED->value, FileStatus::SIGNED->value])) {
4✔
336
                        $nodeId = $fileData->getSignedNodeId();
3✔
337
                } else {
338
                        $nodeId = $fileData->getNodeId();
1✔
339
                }
340
                if ($nodeId === null) {
4✔
341
                        throw new DoesNotExistException('Not found');
×
342
                }
343
                $file = $this->root->getUserFolder($fileData->getUserId())->getFirstNodeById($nodeId);
4✔
344
                if (!$file instanceof File) {
4✔
345
                        throw new DoesNotExistException('Not found');
×
346
                }
347
                return $file;
4✔
348
        }
349

350
        public function getFileByNodeId(int $nodeId): File {
351
                try {
352
                        return $this->folderService->getFileByNodeId($nodeId);
×
353
                } catch (NotFoundException) {
×
354
                        throw new DoesNotExistException('Not found');
×
355
                }
356
        }
357

358
        public function canRequestSign(?IUser $user = null): bool {
359
                if (!$user) {
9✔
360
                        return false;
2✔
361
                }
362
                $authorized = $this->appConfig->getValueArray(Application::APP_ID, 'groups_request_sign', ['admin']);
7✔
363
                if (empty($authorized)) {
7✔
364
                        return false;
2✔
365
                }
366
                $userGroups = $this->groupManager->getUserGroupIds($user);
5✔
367
                if (!array_intersect($userGroups, $authorized)) {
5✔
368
                        return false;
3✔
369
                }
370
                return true;
2✔
371
        }
372

373
        public function getSettings(?IUser $user = null): array {
374
                $return['canRequestSign'] = $this->canRequestSign($user);
1✔
375
                $return['hasSignatureFile'] = $this->hasSignatureFile($user);
1✔
376
                return $return;
1✔
377
        }
378

379
        public function addFilesToAccount(array $files, IUser $user): void {
380
                $this->idDocsService->addIdDocs($files, $user);
×
381
        }
382

383
        public function deleteFileFromAccount(int $nodeId, IUser $user): void {
384
                $this->idDocsService->deleteIdDoc($nodeId, $user);
×
385
        }
386

387
        public function saveVisibleElements(array $elements, string $sessionId, ?IUser $user): void {
388
                foreach ($elements as $element) {
×
389
                        $this->saveVisibleElement($element, $sessionId, $user);
×
390
                }
391
        }
392

393
        public function saveVisibleElement(array $data, string $sessionId, ?IUser $user): void {
394
                if (isset($data['elementId'])) {
×
395
                        $this->updateFileOfVisibleElement($data);
×
396
                        $this->updateDataOfVisibleElement($data);
×
397
                } elseif ($user instanceof IUser) {
×
398
                        $file = $this->saveFileOfVisibleElementUsingUser($data, $user);
×
399
                        $this->insertVisibleElement($data, $user, $file);
×
400
                } else {
401
                        $file = $this->saveFileOfVisibleElementUsingSession($data, $sessionId);
×
402
                }
403
        }
404

405
        private function updateFileOfVisibleElement(array $data): void {
406
                if (!isset($data['file'])) {
×
407
                        return;
×
408
                }
409
                $userElement = $this->userElementMapper->findOne(['id' => $data['elementId']]);
×
410
                $file = $this->folderService->getFileByNodeId($userElement->getNodeId());
×
411
                $file->putContent($this->getFileRaw($data));
×
412
        }
413

414
        private function updateDataOfVisibleElement(array $data): void {
415
                if (!isset($data['starred'])) {
×
416
                        return;
×
417
                }
418
                $userElement = $this->userElementMapper->findOne(['id' => $data['elementId']]);
×
419
                $userElement->setStarred($data['starred'] ? 1 : 0);
×
420
                $this->userElementMapper->update($userElement);
×
421
        }
422

423
        private function saveFileOfVisibleElementUsingUser(array $data, IUser $user): File {
424
                $rootSignatureFolder = $this->folderService->getFolder();
×
425
                $folderName = $this->folderService->getFolderName($data, $user);
×
426
                $folderToFile = $rootSignatureFolder->newFolder($folderName);
×
427
                return $folderToFile->newFile(UUIDUtil::getUUID() . '.png', $this->getFileRaw($data));
×
428
        }
429

430
        private function saveFileOfVisibleElementUsingSession(array $data, string $sessionId): File {
431
                if (!empty($data['nodeId'])) {
×
432
                        return $this->updateFileOfVisibleElementUsingSession($data, $sessionId);
×
433
                }
434
                return $this->createFileOfVisibleElementUsingSession($data, $sessionId);
×
435
        }
436

437
        private function updateFileOfVisibleElementUsingSession(array $data, string $sessionId): File {
438
                $fileList = $this->signerElementsService->getElementsFromSession();
×
439
                $element = array_filter($fileList, fn (File $element) => $element->getId() === $data['nodeId']);
×
440
                $element = current($element);
×
441
                if (!$element instanceof File) {
×
442
                        throw new \Exception($this->l10n->t('File not found'));
×
443
                }
444
                $element->putContent($this->getFileRaw($data));
×
445
                return $element;
×
446
        }
447

448
        private function createFileOfVisibleElementUsingSession(array $data, string $sessionId): File {
449
                $rootSignatureFolder = $this->folderService->getFolder();
×
450
                $folderName = $sessionId;
×
451
                $folderToFile = $rootSignatureFolder->newFolder($folderName);
×
452
                $filename = implode(
×
453
                        '_',
×
454
                        [
×
455
                                $data['type'],
×
456
                                $this->timeFactory->getDateTime()->getTimestamp(),
×
457
                        ]
×
458
                ) . '.png';
×
459
                return $folderToFile->newFile($filename, $this->getFileRaw($data));
×
460
        }
461

462
        private function insertVisibleElement(array $data, IUser $user, File $file): void {
463
                $userElement = new UserElement();
×
464
                $userElement->setType($data['type']);
×
465
                $userElement->setNodeId($file->getId());
×
466
                $userElement->setUserId($user->getUID());
×
467
                $userElement->setStarred(isset($data['starred']) && $data['starred'] ? 1 : 0);
×
468
                $userElement->setCreatedAt($this->timeFactory->getDateTime());
×
469
                $this->userElementMapper->insert($userElement);
×
470
        }
471

472
        private function getFileRaw(array $data): string {
473
                if (!empty($data['file']['url'])) {
×
474
                        if (!filter_var($data['file']['url'], FILTER_VALIDATE_URL)) {
×
475
                                throw new \Exception($this->l10n->t('Invalid URL file'));
×
476
                        }
477
                        $response = $this->clientService->newClient()->get($data['file']['url']);
×
478
                        $contentType = $response->getHeader('Content-Type');
×
479
                        if ($contentType !== 'image/png') {
×
480
                                throw new \Exception($this->l10n->t('Visible element file must be png.'));
×
481
                        }
482
                        $content = (string)$response->getBody();
×
483
                        if (empty($content)) {
×
484
                                throw new \Exception($this->l10n->t('Empty file'));
×
485
                        }
486
                        $this->validateHelper->validateBase64($content, ValidateHelper::TYPE_VISIBLE_ELEMENT_USER);
×
487
                        return $content;
×
488
                }
489
                $this->validateHelper->validateBase64($data['file']['base64'], ValidateHelper::TYPE_VISIBLE_ELEMENT_USER);
×
490
                $withMime = explode(',', (string)$data['file']['base64']);
×
491
                if (count($withMime) === 2) {
×
492
                        $content = base64_decode($withMime[1]);
×
493
                } else {
494
                        $content = base64_decode((string)$data['file']['base64']);
×
495
                }
496
                if (!$content) {
×
497
                        return '';
×
498
                }
499
                return $content;
×
500
        }
501

502
        public function deleteSignatureElement(?IUser $user, string $sessionId, int $nodeId): void {
503
                if ($user instanceof IUser) {
8✔
504
                        $element = $this->userElementMapper->findOne([
2✔
505
                                'node_id' => $nodeId,
2✔
506
                                'user_id' => $user->getUID(),
2✔
507
                        ]);
2✔
508
                        $this->userElementMapper->delete($element);
2✔
509
                        try {
510
                                $file = $this->folderService->getFileByNodeId($element->getNodeId());
2✔
511
                                $file->delete();
1✔
512
                        } catch (NotFoundException) {
1✔
513
                        }
514
                        return;
2✔
515
                }
516

517
                $this->deleteSignatureElementFromSession($sessionId, $nodeId);
6✔
518
        }
519

520
        private function deleteSignatureElementFromSession(string $sessionId, int $nodeId): void {
521
                $rootSignatureFolder = $this->folderService->getFolder();
6✔
522
                try {
523
                        /** @var \OCP\Files\Folder $sessionFolder */
524
                        $sessionFolder = $rootSignatureFolder->get($sessionId);
6✔
525
                } catch (NotFoundException) {
1✔
526
                        throw new DoesNotExistException($this->l10n->t('Element not found'));
1✔
527
                }
528

529
                $element = $sessionFolder->getFirstNodeById($nodeId);
5✔
530
                if (!$element instanceof File) {
5✔
531
                        throw new DoesNotExistException($this->l10n->t('Element not found'));
2✔
532
                }
533
                $element->delete();
3✔
534

535
                // Clean up empty session folder
536
                if (count($sessionFolder->getDirectoryListing()) === 0) {
3✔
537
                        $sessionFolder->delete();
2✔
538
                }
539
        }
540

541
        /**
542
         * @throws LibresignException at savePfx
543
         * @throws InvalidArgumentException
544
         */
545
        public function uploadPfx(array $file, IUser $user): void {
546
                try {
547
                        $this->uploadHelper->validateUploadedFile($file);
×
548
                } catch (InvalidArgumentException) {
×
549
                        // TRANSLATORS Error when the uploaded certificate file is not valid
550
                        throw new InvalidArgumentException($this->l10n->t('Invalid file provided. Need to be a .pfx file.'));
×
551
                }
552

553
                if ($file['size'] > 10 * 1024) {
×
554
                        // TRANSLATORS Error when the certificate file is bigger than normal
555
                        throw new InvalidArgumentException($this->l10n->t('File is too big'));
×
556
                }
557
                $content = file_get_contents($file['tmp_name']);
×
558
                $mimetype = $this->mimeTypeDetector->detectString($content);
×
559
                if ($mimetype !== 'application/octet-stream') {
×
560
                        // TRANSLATORS Error when the mimetype of uploaded file is not valid
561
                        throw new InvalidArgumentException($this->l10n->t('Invalid file provided. Need to be a .pfx file.'));
×
562
                }
563
                $extension = strtolower(pathinfo((string)$file['name'], PATHINFO_EXTENSION));
×
564
                if ($extension !== 'pfx') {
×
565
                        // TRANSLATORS Error when the certificate file is not a pfx file
566
                        throw new InvalidArgumentException($this->l10n->t('Invalid file provided. Need to be a .pfx file.'));
×
567
                }
568
                unlink($file['tmp_name']);
×
569
                $this->pkcs12Handler->savePfx($user->getUID(), $content);
×
570
        }
571

572
        public function deletePfx(IUser $user): void {
573
                $this->pkcs12Handler->deletePfx($user->getUID());
×
574
        }
575

576
        /**
577
         * @throws LibresignException when have not a certificate file
578
         */
579
        public function updatePfxPassword(IUser $user, string $current, string $new): void {
580
                try {
581
                        $pfx = $this->pkcs12Handler->updatePassword($user->getUID(), $current, $new);
×
582
                } catch (InvalidPasswordException) {
×
583
                        throw new LibresignException($this->l10n->t('Invalid user or password'));
×
584
                }
585
        }
586

587
        /**
588
         * @throws LibresignException when have not a certificate file
589
         */
590
        public function readPfxData(IUser $user, string $password): array {
591
                try {
592
                        return $this->pkcs12Handler
×
593
                                ->setCertificate($this->pkcs12Handler->getPfxOfCurrentSigner($user->getUID()))
×
594
                                ->setPassword($password)
×
595
                                ->readCertificate();
×
596
                } catch (InvalidPasswordException) {
×
597
                        throw new LibresignException($this->l10n->t('Invalid user or password'));
×
598
                }
599
        }
600
}
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