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

LibreSign / libresign / 22047397566

16 Feb 2026 01:47AM UTC coverage: 51.605%. First build
22047397566

Pull #6891

github

web-flow
Merge cc204601c into bdac9dc51
Pull Request #6891: feat: add id doc approver workflow

171 of 424 new or added lines in 24 files covered. (40.33%)

9145 of 17721 relevant lines covered (51.61%)

6.15 hits per line

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

91.8
/lib/Service/File/SettingsLoader.php
1
<?php
2

3
declare(strict_types=1);
4

5
/**
6
 * SPDX-FileCopyrightText: 2025 LibreCode coop and contributors
7
 * SPDX-License-Identifier: AGPL-3.0-or-later
8
 */
9

10
namespace OCA\Libresign\Service\File;
11

12
use OCA\Libresign\AppInfo\Application;
13
use OCA\Libresign\Db\File;
14
use OCA\Libresign\Db\IdDocsMapper;
15
use OCA\Libresign\Db\SignRequest;
16
use OCA\Libresign\Enum\FileStatus;
17
use OCA\Libresign\ResponseDefinitions;
18
use OCA\Libresign\Service\IdDocsPolicyService;
19
use OCA\Libresign\Service\IdentifyMethodService;
20
use OCP\IAppConfig;
21
use OCP\IGroupManager;
22
use OCP\IUser;
23
use stdClass;
24

25
/**
26
 * @psalm-import-type LibresignSettings from ResponseDefinitions
27
 */
28
class SettingsLoader {
29
        public const IDENTIFICATION_DOCUMENTS_DISABLED = 0;
30
        public const IDENTIFICATION_DOCUMENTS_NEED_SEND = 1;
31
        public const IDENTIFICATION_DOCUMENTS_NEED_APPROVAL = 2;
32
        public const IDENTIFICATION_DOCUMENTS_APPROVED = 3;
33

34
        public function __construct(
35
                private AccountSettingsProvider $accountSettingsProvider,
36
                private IdDocsPolicyService $idDocsPolicyService,
37
                private IAppConfig $appConfig,
38
                private IGroupManager $groupManager,
39
                private IdDocsMapper $idDocsMapper,
40
                private IdentifyMethodService $identifyMethodService,
41
        ) {
42
        }
47✔
43

44
        public function loadSettings(
45
                stdClass $fileData,
46
                FileResponseOptions $options,
47
        ): void {
48
                if (!$options->isShowSettings()) {
8✔
49
                        return;
1✔
50
                }
51

52
                $fileData->settings = $this->getUserIdentificationSettings($options->getMe(), $options->getSignRequest());
7✔
53

54
                if ($options->getMe()) {
7✔
55
                        $fileData->settings = array_merge(
3✔
56
                                $fileData->settings,
3✔
57
                                $this->accountSettingsProvider->getSettings($options->getMe()),
3✔
58
                        );
3✔
59
                        $fileData->settings['phoneNumber'] = $this->accountSettingsProvider->getPhoneNumber($options->getMe());
3✔
60
                        if ($this->idDocsPolicyService->canApproverSignIdDoc(
3✔
61
                                $options->getMe(),
3✔
62
                                $fileData->id,
3✔
63
                                $fileData->status,
3✔
64
                        )) {
3✔
65
                                $fileData->settings['canSign'] = true;
1✔
66
                                $fileData->settings['isApprover'] = true;
1✔
67
                                $this->loadApproverSignatureMethods($fileData);
1✔
68
                        }
69
                }
70
        }
71

72
        private function loadApproverSignatureMethods(stdClass $fileData): void {
73
                try {
74
                        $idDocs = $this->idDocsMapper->getByFileId($fileData->id);
1✔
75
                        $signRequestId = $idDocs->getSignRequestId();
1✔
76
                        if (!$signRequestId) {
1✔
77
                                return;
1✔
78
                        }
79

NEW
80
                        $signatureMethods = $this->identifyMethodService->getSignMethodsOfIdentifiedFactors($signRequestId);
×
NEW
81
                        $fileData->settings['signatureMethods'] = $signatureMethods;
×
NEW
82
                } catch (\Throwable) {
×
83
                }
84
        }
85

86
        public function getIdentificationDocumentsStatus(?IUser $user = null, ?SignRequest $signRequest = null): int {
87
                if (!$this->appConfig->getValueBool(Application::APP_ID, 'identification_documents', false)) {
20✔
88
                        return self::IDENTIFICATION_DOCUMENTS_DISABLED;
10✔
89
                }
90

91
                $approvalGroups = $this->appConfig->getValueArray(Application::APP_ID, 'approval_group', ['admin']);
10✔
92
                if ($user && !empty($approvalGroups) && is_array($approvalGroups)) {
10✔
93
                        $userGroups = $this->groupManager->getUserGroupIds($user);
7✔
94
                        if (array_intersect($userGroups, $approvalGroups)) {
7✔
NEW
95
                                return self::IDENTIFICATION_DOCUMENTS_APPROVED;
×
96
                        }
97
                }
98

99
                $files = $this->getIdDocFiles($user, $signRequest);
10✔
100

101
                return $this->calculateStatusFromFiles($files);
10✔
102
        }
103

104
        private function getIdDocFiles(?IUser $user, ?SignRequest $signRequest): ?array {
105
                if ($user) {
10✔
106
                        return $this->idDocsMapper->getFilesOfAccount($user->getUID());
7✔
107
                }
108

109
                if ($signRequest) {
3✔
NEW
110
                        return $this->idDocsMapper->getFilesOfSignRequest($signRequest->getId());
×
111
                }
112

113
                return null;
3✔
114
        }
115

116
        private function calculateStatusFromFiles(?array $files): int {
117
                if (empty($files)) {
10✔
118
                        return self::IDENTIFICATION_DOCUMENTS_NEED_SEND;
5✔
119
                }
120

121
                $deleted = array_filter($files, fn (File $file) => $file->getStatus() === FileStatus::DELETED->value);
5✔
122
                if (count($deleted) === count($files)) {
5✔
123
                        return self::IDENTIFICATION_DOCUMENTS_NEED_SEND;
1✔
124
                }
125

126
                $signed = array_filter($files, fn (File $file) => $file->getStatus() === FileStatus::SIGNED->value);
4✔
127
                if (count($signed) !== count($files)) {
4✔
128
                        return self::IDENTIFICATION_DOCUMENTS_NEED_APPROVAL;
2✔
129
                }
130

131
                return self::IDENTIFICATION_DOCUMENTS_APPROVED;
2✔
132
        }
133

134
        /**
135
         * Get user identification documents settings
136
         * These are user-specific settings, not file-specific
137
         * Always returns complete LibresignSettings with defaults
138
         *
139
         * @psalm-return LibresignSettings
140
         */
141
        public function getUserIdentificationSettings(?IUser $user, ?SignRequest $signRequest = null): array {
142
                $status = $this->getIdentificationDocumentsStatus($user, $signRequest);
12✔
143

144
                return [
12✔
145
                        'canSign' => false,
12✔
146
                        'canRequestSign' => false,
12✔
147
                        'signerFileUuid' => null,
12✔
148
                        'phoneNumber' => '',
12✔
149
                        'hasSignatureFile' => false,
12✔
150
                        'needIdentificationDocuments' => in_array($status, [
12✔
151
                                self::IDENTIFICATION_DOCUMENTS_NEED_SEND,
12✔
152
                                self::IDENTIFICATION_DOCUMENTS_NEED_APPROVAL,
12✔
153
                        ], true),
12✔
154
                        'identificationDocumentsWaitingApproval' => $status === self::IDENTIFICATION_DOCUMENTS_NEED_APPROVAL,
12✔
155
                ];
12✔
156
        }
157
}
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