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

LibreSign / libresign / 20472217448

23 Dec 2025 09:41PM UTC coverage: 42.655%. First build
20472217448

Pull #6242

github

web-flow
Merge 5e8e97740 into 4f1a71d46
Pull Request #6242: feat: envelope support

301 of 1003 new or added lines in 21 files covered. (30.01%)

6159 of 14439 relevant lines covered (42.66%)

4.97 hits per line

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

72.17
/lib/Service/IdentifyMethodService.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 OCA\Libresign\Db\IdentifyMethod;
12
use OCA\Libresign\Db\IdentifyMethodMapper;
13
use OCA\Libresign\Db\SignRequest;
14
use OCA\Libresign\Exception\LibresignException;
15
use OCA\Libresign\Service\IdentifyMethod\Account;
16
use OCA\Libresign\Service\IdentifyMethod\Email;
17
use OCA\Libresign\Service\IdentifyMethod\IIdentifyMethod;
18
use OCA\Libresign\Service\IdentifyMethod\Signal;
19
use OCA\Libresign\Service\IdentifyMethod\Sms;
20
use OCA\Libresign\Service\IdentifyMethod\Telegram;
21
use OCA\Libresign\Service\IdentifyMethod\Whatsapp;
22
use OCA\Libresign\Service\IdentifyMethod\Xmpp;
23
use OCP\IConfig;
24
use OCP\IL10N;
25

26
class IdentifyMethodService {
27
        public const IDENTIFY_ACCOUNT = 'account';
28
        public const IDENTIFY_EMAIL = 'email';
29
        public const IDENTIFY_SIGNAL = 'signal';
30
        public const IDENTIFY_TELEGRAM = 'telegram';
31
        public const IDENTIFY_SMS = 'sms';
32
        public const IDENTIFY_WHATSAPP = 'whatsapp';
33
        public const IDENTIFY_XMPP = 'xmpp';
34
        public const IDENTIFY_PASSWORD = 'password';
35
        public const IDENTIFY_CLICK_TO_SIGN = 'clickToSign';
36
        public const IDENTIFY_METHODS = [
37
                self::IDENTIFY_ACCOUNT,
38
                self::IDENTIFY_EMAIL,
39
                self::IDENTIFY_SIGNAL,
40
                self::IDENTIFY_TELEGRAM,
41
                self::IDENTIFY_SMS,
42
                self::IDENTIFY_WHATSAPP,
43
                self::IDENTIFY_XMPP,
44
                self::IDENTIFY_PASSWORD,
45
                self::IDENTIFY_CLICK_TO_SIGN,
46
        ];
47
        private bool $isRequest = true;
48
        private ?IdentifyMethod $currentIdentifyMethod = null;
49
        private array $identifyMethodsSettings = [];
50
        /**
51
         * @var array<string,array<IIdentifyMethod>>
52
         */
53
        private array $identifyMethods = [];
54

55
        public function __construct(
56
                private IConfig $config,
57
                private IdentifyMethodMapper $identifyMethodMapper,
58
                private IL10N $l10n,
59
                private Account $account,
60
                private Email $email,
61
                private Signal $signal,
62
                private Sms $sms,
63
                private Telegram $telegram,
64
                private Whatsapp $whatsapp,
65
                private Xmpp $xmpp,
66
        ) {
67
        }
47✔
68

69
        public function clearCache(): void {
NEW
70
                $this->identifyMethods = [];
×
NEW
71
                $this->currentIdentifyMethod = null;
×
72
        }
73

74
        public function setIsRequest(bool $isRequest): self {
75
                $this->isRequest = $isRequest;
4✔
76
                return $this;
4✔
77
        }
78

79
        public function getInstanceOfIdentifyMethod(string $name, ?string $identifyValue = null): IIdentifyMethod {
80
                if ($identifyValue && isset($this->identifyMethods[$name])) {
13✔
81
                        foreach ($this->identifyMethods[$name] as $identifyMethod) {
10✔
82
                                if ($identifyMethod->getEntity()->getIdentifierValue() === $identifyValue) {
10✔
83
                                        $identifyMethod = $this->mergeWithCurrentIdentifyMethod($identifyMethod);
10✔
84
                                        return $identifyMethod;
10✔
85
                                }
86
                        }
87
                }
88
                $identifyMethod = $this->getNewInstanceOfMethod($name);
13✔
89

90
                $entity = $identifyMethod->getEntity();
13✔
91
                if (!$entity->getId()) {
13✔
92
                        $entity->setIdentifierKey($name);
13✔
93
                        $entity->setIdentifierValue($identifyValue);
13✔
94
                        $entity->setMandatory($this->isMandatoryMethod($name) ? 1 : 0);
13✔
95
                }
96
                if ($identifyValue && $this->isRequest) {
13✔
97
                        $identifyMethod->validateToRequest();
13✔
98
                }
99

100
                $this->identifyMethods[$name][] = $identifyMethod;
13✔
101
                return $identifyMethod;
13✔
102
        }
103

104
        private function mergeWithCurrentIdentifyMethod(IIdentifyMethod $identifyMethod): IIdentifyMethod {
105
                if ($this->currentIdentifyMethod === null) {
10✔
106
                        return $identifyMethod;
2✔
107
                }
108
                if ($this->currentIdentifyMethod->getIdentifierKey() === $identifyMethod->getEntity()->getIdentifierKey()
10✔
109
                        && $this->currentIdentifyMethod->getIdentifierValue() === $identifyMethod->getEntity()->getIdentifierValue()
10✔
110
                ) {
111
                        $identifyMethod->setEntity($this->currentIdentifyMethod);
10✔
112
                }
113
                return $identifyMethod;
10✔
114
        }
115

116
        private function getNewInstanceOfMethod(string $name): IIdentifyMethod {
117
                $className = 'OCA\Libresign\Service\IdentifyMethod\\' . ucfirst($name);
13✔
118
                if (!class_exists($className)) {
13✔
119
                        $className = 'OCA\Libresign\Service\IdentifyMethod\\SignatureMethod\\' . ucfirst($name);
×
120
                        if (!class_exists($className)) {
×
121
                                // TRANSLATORS When is requested to a person to sign a file, is
122
                                // necessary identify what is the identification method. The
123
                                // identification method is used to define how will be the sign
124
                                // flow.
125
                                throw new LibresignException($this->l10n->t('Invalid identification method'));
×
126
                        }
127
                }
128
                /** @var IIdentifyMethod */
129
                $identifyMethod = clone \OCP\Server::get($className);
13✔
130
                if (empty($this->currentIdentifyMethod)) {
13✔
131
                        $identifyMethod->cleanEntity();
13✔
132
                } else {
133
                        $identifyMethod->setEntity($this->currentIdentifyMethod);
×
134
                }
135
                $identifyMethod->getSettings();
13✔
136
                return $identifyMethod;
13✔
137
        }
138

139
        private function setEntityData(string $method, string $identifyValue): void {
140
                // @todo Replace by enum when PHP 8.1 is the minimum version acceptable
141
                // at server. Check file lib/versioncheck.php of server repository
142
                if (!in_array($method, IdentifyMethodService::IDENTIFY_METHODS)) {
1✔
143
                        // TRANSLATORS When is requested to a person to sign a file, is
144
                        // necessary identify what is the identification method. The
145
                        // identification method is used to define how will be the sign
146
                        // flow.
147
                        throw new LibresignException($this->l10n->t('Invalid identification method'));
×
148
                }
149
                $identifyMethod = $this->getInstanceOfIdentifyMethod($method, $identifyValue);
1✔
150
                $identifyMethod->validateToRequest();
1✔
151
        }
152

153
        public function setAllEntityData(array $user): void {
154
                foreach ($user['identify'] as $method => $identifyValue) {
1✔
155
                        $this->setEntityData($method, $identifyValue);
1✔
156
                }
157
        }
158

159
        private function isMandatoryMethod(string $methodName): bool {
160
                $settings = $this->getIdentifyMethodsSettings();
13✔
161
                foreach ($settings as $setting) {
13✔
162
                        if ($setting['name'] === $methodName) {
13✔
163
                                return $setting['mandatory'];
13✔
164
                        }
165
                }
166
                return false;
×
167
        }
168

169
        /**
170
         * @return array<IIdentifyMethod>
171
         */
172
        public function getByUserData(array $data) {
173
                $return = [];
13✔
174
                foreach ($data as $method => $identifyValue) {
13✔
175
                        $this->setCurrentIdentifyMethod();
13✔
176
                        $return[] = $this->getInstanceOfIdentifyMethod($method, $identifyValue);
13✔
177
                }
178
                return $return;
13✔
179
        }
180

181
        public function setCurrentIdentifyMethod(?IdentifyMethod $entity = null): self {
182
                $this->currentIdentifyMethod = $entity;
13✔
183
                return $this;
13✔
184
        }
185

186
        /**
187
         * @return array<string,array<IIdentifyMethod>>
188
         */
189
        public function getIdentifyMethodsFromSignRequestId(int $signRequestId): array {
190
                $entities = $this->identifyMethodMapper->getIdentifyMethodsFromSignRequestId($signRequestId);
10✔
191
                foreach ($entities as $entity) {
10✔
192
                        $this->setCurrentIdentifyMethod($entity);
10✔
193
                        $this->getInstanceOfIdentifyMethod(
10✔
194
                                $entity->getIdentifierKey(),
10✔
195
                                $entity->getIdentifierValue(),
10✔
196
                        );
10✔
197
                }
198
                $return = [];
10✔
199
                foreach ($this->identifyMethods as $methodName => $list) {
10✔
200
                        foreach ($list as $method) {
10✔
201
                                if ($method->getEntity()->getSignRequestId() === $signRequestId) {
10✔
202
                                        $return[$methodName][] = $method;
10✔
203
                                }
204
                        }
205
                }
206
                return $return;
10✔
207
        }
208

209
        public function getIdentifiedMethod(int $signRequestId): IIdentifyMethod {
210
                $matrix = $this->getIdentifyMethodsFromSignRequestId($signRequestId);
×
211
                foreach ($matrix as $identifyMethods) {
×
212
                        foreach ($identifyMethods as $identifyMethod) {
×
213
                                if ($identifyMethod->getEntity()->getIdentifiedAtDate()) {
×
214
                                        return $identifyMethod;
×
215
                                }
216
                        }
217
                }
218
                throw new LibresignException($this->l10n->t('Invalid identification method'), 1);
×
219
        }
220

221
        public function getSignMethodsOfIdentifiedFactors(int $signRequestId): array {
222
                $matrix = $this->getIdentifyMethodsFromSignRequestId($signRequestId);
3✔
223
                $return = [];
3✔
224
                foreach ($matrix as $identifyMethods) {
3✔
225
                        foreach ($identifyMethods as $identifyMethod) {
3✔
226
                                $signatureMethods = $identifyMethod->getSignatureMethods();
3✔
227
                                foreach ($signatureMethods as $signatureMethod) {
3✔
228
                                        if (!$signatureMethod->isEnabled()) {
3✔
229
                                                continue;
3✔
230
                                        }
231
                                        $signatureMethod->setEntity($identifyMethod->getEntity());
3✔
232
                                        $return[$signatureMethod->getName()] = $signatureMethod->toArray();
3✔
233
                                }
234
                        }
235
                }
236
                return $return;
3✔
237
        }
238

239
        public function save(SignRequest $signRequest, bool $notify = true): void {
240
                foreach ($this->identifyMethods as $methods) {
×
241
                        foreach ($methods as $identifyMethod) {
×
242
                                $entity = $identifyMethod->getEntity();
×
243
                                $entity->setSignRequestId($signRequest->getId());
×
244
                                if ($entity->getId()) {
×
245
                                        $entity = $this->identifyMethodMapper->update($entity);
×
246
                                        if ($notify) {
×
247
                                                $identifyMethod->willNotifyUser(false);
×
248
                                                $identifyMethod->notify();
×
249
                                        }
250
                                } else {
251
                                        $entity = $this->identifyMethodMapper->insert($entity);
×
252
                                        if ($notify) {
×
253
                                                $identifyMethod->willNotifyUser(true);
×
254
                                                $identifyMethod->notify();
×
255
                                        }
256
                                }
257
                        }
258
                }
259
        }
260

261
        public function getIdentifyMethodsSettings(): array {
262
                if ($this->identifyMethodsSettings) {
13✔
263
                        return $this->identifyMethodsSettings;
1✔
264
                }
265
                $this->identifyMethodsSettings = [
13✔
266
                        $this->account->getSettings(),
13✔
267
                        $this->email->getSettings(),
13✔
268
                ];
13✔
269
                if ($this->signal->isTwofactorGatewayEnabled()) {
13✔
270
                        $this->identifyMethodsSettings[] = $this->signal->getSettings();
×
271
                }
272
                if ($this->sms->isTwofactorGatewayEnabled()) {
13✔
273
                        $this->identifyMethodsSettings[] = $this->sms->getSettings();
×
274
                }
275
                if ($this->telegram->isTwofactorGatewayEnabled()) {
13✔
276
                        $this->identifyMethodsSettings[] = $this->telegram->getSettings();
×
277
                }
278
                if ($this->whatsapp->isTwofactorGatewayEnabled()) {
13✔
279
                        $this->identifyMethodsSettings[] = $this->whatsapp->getSettings();
×
280
                }
281
                if ($this->xmpp->isTwofactorGatewayEnabled()) {
13✔
282
                        $this->identifyMethodsSettings[] = $this->xmpp->getSettings();
×
283
                }
284
                return $this->identifyMethodsSettings;
13✔
285
        }
286
}
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

© 2025 Coveralls, Inc