Passed
Push — master ( 106709...350f1a )
by Nils
07:20
created

UserHandlerTrait::generateNewUserStep20()   B

Complexity

Conditions 9
Paths 16

Size

Total Lines 65
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 9
eloc 35
nc 16
nop 2
dl 0
loc 65
rs 8.0555
c 1
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Teampass - a collaborative passwords manager.
4
 * ---
5
 * This file is part of the TeamPass project.
6
 * 
7
 * TeamPass is free software: you can redistribute it and/or modify it
8
 * under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation, version 3 of the License.
10
 * 
11
 * TeamPass is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
 * GNU General Public License for more details.
15
 * 
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18
 * 
19
 * Certain components of this file may be under different licenses. For
20
 * details, see the `licenses` directory or individual file headers.
21
 * ---
22
 * @file      UserHandlerTrait.php
23
 * @author    Nils Laumaillé ([email protected])
24
 * @copyright 2009-2025 Teampass.net
25
 * @license   GPL-3.0
26
 * @see       https://www.teampass.net
27
 */
28
29
use TeampassClasses\Language\Language;
30
31
trait UserHandlerTrait {
32
    abstract protected function completeTask();
33
34
    /**
35
     * Handle user build cache tree
36
     * @param array $arguments Useful arguments for the task
37
     * @return void
38
     */
39
    private function handleUserBuildCacheTree($arguments) {
40
        performVisibleFoldersHtmlUpdate($arguments['user_id']);
41
    }
42
43
44
    /**
45
     * Generate user keys
46
     * @param array $taskData Données de la tâche
47
     * @param array $arguments Arguments nécessaires pour la création des clés
48
     * @return void
49
     */
50
    private function generateUserKeys($arguments) {
51
        // Get all subtasks related to this task
52
        $subtasks = DB::query(
53
            'SELECT * FROM ' . prefixTable('background_subtasks') . ' WHERE task_id = %i AND is_in_progress = 0 ORDER BY `task` ASC',
54
            $this->taskId
55
        );
56
    
57
        if (empty($subtasks)) {
58
            if (LOG_TASKS=== true) $this->logger->log("No subtask was found for task {$this->taskId}");
59
            return;
60
        }
61
    
62
        // Process each subtask
63
        foreach ($subtasks as $subtask) {
64
            if (LOG_TASKS=== true) $this->logger->log("Processing subtask {$subtask['increment_id']} for task {$this->taskId}");
65
            $this->processGenerateUserKeysSubtask($subtask, $arguments);
66
        }
67
    
68
        // Are all subtasks completed?
69
        $remainingSubtasks = DB::queryFirstField(
70
            'SELECT COUNT(*) FROM ' . prefixTable('background_subtasks') . ' WHERE task_id = %i AND is_in_progress = 0',
71
            $this->taskId
72
        );    
73
        if ($remainingSubtasks == 0) {
74
            $this->completeTask();
75
        }
76
    }
77
    
78
79
    /**
80
     * Process a subtask for generating user keys.
81
     * @param array $subtask The subtask to process.
82
     * @param array $arguments Arguments for the task.
83
     * @return void
84
     */
85
    private function processGenerateUserKeysSubtask(array $subtask, array $arguments) {
86
        try {
87
            $taskData = json_decode($subtask['task'], true);
88
            
89
            // Mark the subtask as in progress
90
            DB::update(
91
                prefixTable('background_subtasks'),
92
                [
93
                    'is_in_progress' => 1,
94
                    'updated_at' => time(),
95
                    'status' => 'in progress'
96
                ],
97
                'increment_id = %i',
98
                $subtask['increment_id']
99
            );
100
            
101
            if (LOG_TASKS=== true) $this->logger->log("Subtask is in progress: ".$taskData['step'], 'INFO');
102
            switch ($taskData['step'] ?? '') {
103
                case 'step0':
104
                    $this->generateNewUserStep0($arguments);
105
                    break;
106
                case 'step20':
107
                    $this->generateNewUserStep20($taskData, $arguments);
108
                    break;
109
                case 'step30':
110
                    $this->generateNewUserStep30($taskData, $arguments);
111
                    break;
112
                case 'step40':
113
                    $this->generateNewUserStep40($taskData, $arguments);
114
                    break;
115
                case 'step50':
116
                    $this->generateNewUserStep50($taskData, $arguments);
117
                    break;
118
                case 'step60':
119
                    $this->generateNewUserStep60($taskData, $arguments);
120
                    break;
121
                case 'step99':
122
                    $this->generateNewUserStep99($arguments);
123
                break;
124
                default:
125
                    throw new Exception("Type of subtask unknown: {$this->processType}");
126
            }
127
    
128
            // Mark subtask as completed
129
            DB::update(
130
                prefixTable('background_subtasks'),
131
                [
132
                    'is_in_progress' => -1,
133
                    'finished_at' => time(),
134
                    'status' => 'completed',
135
                ],
136
                'increment_id = %i',
137
                $subtask['increment_id']
138
            );
139
    
140
        } catch (Exception $e) {
141
            // Failure handling
142
            DB::update(
143
                prefixTable('background_subtasks'),
144
                [
145
                    'is_in_progress' => -1,
146
                    'finished_at' => time(),
147
                    'updated_at' => time(),
148
                    'status' => 'failed',
149
                    'error_message' => $e->getMessage(),
150
                ],
151
                'increment_id = %i',
152
                $subtask['increment_id']
153
            );
154
            
155
            $this->logger->log("Subtask {$subtask['increment_id']} failure: " . $e->getMessage(), 'ERROR');
156
        }
157
    }
158
    
159
160
    /**
161
     * Generate new user keys - step 0
162
     * @param array $arguments Arguments for the task
163
     * @return void
164
     */
165
    private function generateNewUserStep0($arguments) {
166
        // CLear old sharekeys
167
        if ($arguments['user_self_change'] === 0) {
168
            if (LOG_TASKS=== true) $this->logger->log("Deleting old sharekeys for user {$arguments['new_user_id']}", 'INFO');
169
            deleteUserObjetsKeys($arguments['new_user_id'], $this->settings);
170
        }
171
    }
172
173
174
    /**
175
     * Generate new user keys
176
     * @param array $taskData Task data
177
     * @param array $arguments Arguments for the task
178
     */
179
    private function generateNewUserStep20($taskData, $arguments) {
180
        // get user private key
181
        $ownerInfo = isset($arguments['owner_id']) && isset($arguments['creator_pwd']) 
182
            ? $this->getOwnerInfos($arguments['owner_id'], $arguments['creator_pwd']) 
183
            : null;
184
        $userInfo = $this->getOwnerInfos(
185
            $arguments['new_user_id'],
186
            empty($arguments['new_user_pwd']) === false ? $arguments['new_user_pwd'] : $arguments['new_user_code'],
187
            ((int) $arguments['only_personal_items'] ?? 0) === 1 ? 1 : 0,
188
            $arguments['new_user_private_key'] ?? ''
189
        );
190
191
        // Start transaction for better performance
192
        DB::startTransaction();
193
194
        // Loop on items
195
        $rows = DB::query(
196
            'SELECT id, pw, perso
197
            FROM ' . prefixTable('items') . '
198
            ORDER BY id ASC
199
            LIMIT %i, %i',
200
            $taskData['index'],
201
            $taskData['nb']
202
        );
203
        
204
        foreach ($rows as $record) {
205
            // Get itemKey from current user
206
            $itemShareKey = DB::queryFirstRow(
207
                'SELECT share_key, increment_id
208
                FROM ' . prefixTable('sharekeys_items') . '
209
                WHERE object_id = %i AND user_id = %i',
210
                $record['id'],
211
                (int) $arguments['owner_id']
212
            );
213
214
            // do we have any input? (#3481)
215
            if ($itemShareKey === null || count($itemShareKey) === 0) {
216
                continue;
217
            }
218
            
219
            // Decrypt itemkey with expected private key
220
            $itemKey = decryptUserObjectKey(
221
                $itemShareKey['share_key'],
222
                $ownerInfo['private_key']
223
            );
224
            
225
            // Prevent to change key if its key is empty
226
            if (empty($itemKey) === true) {
227
                $share_key_for_item = '';
228
            } else {
229
                // Encrypt Item key
230
                $share_key_for_item = encryptUserObjectKey($itemKey, $userInfo['public_key']);
231
            }
232
            
233
            // Save the new sharekey correctly encrypted in DB
234
            insertOrUpdateSharekey(
235
                prefixTable('sharekeys_items'),
236
                (int) $record['id'],
237
                (int) $arguments['new_user_id'],
238
                $share_key_for_item
239
            ); 
240
        }
241
242
        // Commit transaction
243
        DB::commit();
244
    }
245
246
247
    /**
248
     * Generate new user keys - step 30
249
     * @param array $taskData Task data
250
     * @param array $arguments Arguments for the task
251
     * @return void
252
     */
253
    private function generateNewUserStep30($taskData, $arguments) {
254
        // get user private key
255
        $ownerInfo = isset($arguments['owner_id']) && isset($arguments['creator_pwd']) 
256
            ? $this->getOwnerInfos($arguments['owner_id'], $arguments['creator_pwd']) 
257
            : null;
258
        $userInfo = $this->getOwnerInfos(
259
            $arguments['new_user_id'],
260
            $arguments['new_user_pwd'],
261
            ($arguments['only_personal_items'] ?? 0) === 1 ? 1 : 0,
262
            $arguments['new_user_private_key'] ?? ''
263
        );
264
265
        // Start transaction for better performance
266
        DB::startTransaction();
267
268
        // Loop on logs
269
        $rows = DB::query(
270
            'SELECT increment_id
271
            FROM ' . prefixTable('log_items') . '
272
            WHERE raison LIKE "at_pw :%" AND encryption_type = "teampass_aes"
273
            ORDER BY increment_id ASC
274
            LIMIT ' . $taskData['index'] . ', ' . $taskData['nb']
275
        );
276
        foreach ($rows as $record) {
277
            // Get itemKey from current user
278
            $currentUserKey = DB::queryFirstRow(
279
                'SELECT share_key
280
                FROM ' . prefixTable('sharekeys_logs') . '
281
                WHERE object_id = %i AND user_id = %i',
282
                $record['increment_id'],
283
                $arguments['owner_id']
284
            );
285
286
            // do we have any input? (#3481)
287
            if ($currentUserKey === null || count($currentUserKey) === 0) {
288
                continue;
289
            }
290
291
            // Decrypt itemkey with admin key
292
            $itemKey = decryptUserObjectKey($currentUserKey['share_key'], $ownerInfo['private_key']);
293
294
            // Encrypt Item key
295
            $share_key_for_item = encryptUserObjectKey($itemKey, $userInfo['public_key']);
296
297
            // Save the key in DB
298
            insertOrUpdateSharekey(
299
                prefixTable('sharekeys_logs'),
300
                (int) $record['increment_id'],
301
                (int) $arguments['new_user_id'],
302
                $share_key_for_item
303
            );
304
        }
305
306
        // Commit transaction
307
        DB::commit();
308
    }
309
310
311
    /**
312
     * Generate new user keys - step 40
313
     * @param array $taskData Task data
314
     * @param array $arguments Arguments for the task
315
     * @return void
316
     */
317
    private function generateNewUserStep40($taskData, $arguments) {
318
        // get user private key
319
        $ownerInfo = isset($arguments['owner_id']) && isset($arguments['creator_pwd']) 
320
            ? $this->getOwnerInfos($arguments['owner_id'], $arguments['creator_pwd']) 
321
            : null;
322
        $userInfo = $this->getOwnerInfos(
323
            $arguments['new_user_id'],
324
            $arguments['new_user_pwd'],
325
            ($arguments['only_personal_items'] ?? 0) === 1 ? 1 : 0,
326
            $arguments['new_user_private_key'] ?? ''
327
        );
328
329
        // Start transaction for better performance
330
        DB::startTransaction();
331
332
        // Loop on fields
333
        $rows = DB::query(
334
            'SELECT id
335
            FROM ' . prefixTable('categories_items') . '
336
            WHERE encryption_type = "teampass_aes"
337
            ORDER BY id ASC
338
            LIMIT %i, %i',
339
            $taskData['index'],
340
            $taskData['nb']
341
        );
342
        foreach ($rows as $record) {
343
            // Get itemKey from current user
344
            $currentUserKey = DB::queryFirstRow(
345
                'SELECT share_key
346
                FROM ' . prefixTable('sharekeys_fields') . '
347
                WHERE object_id = %i AND user_id = %i',
348
                $record['id'],
349
                $arguments['owner_id']
350
            );
351
352
            // do we have any input?
353
            if ($currentUserKey === null || count($currentUserKey) === 0) {
354
                continue;
355
            }
356
            
357
            // Decrypt itemkey with admin key
358
            $itemKey = decryptUserObjectKey($currentUserKey['share_key'], $ownerInfo['private_key']);
359
360
            // Encrypt Item key
361
            $share_key_for_item = encryptUserObjectKey($itemKey, $userInfo['public_key']);
362
363
            // Save the key in DB
364
            insertOrUpdateSharekey(
365
                prefixTable('sharekeys_fields'),
366
                (int) $record['id'],
367
                (int) $arguments['new_user_id'],
368
                $share_key_for_item
369
            );
370
        }
371
372
        // Commit transaction
373
        DB::commit();
374
    }
375
376
377
    /**
378
     * Generate new user keys - step 50
379
     * @param array $taskData Task data
380
     * @param array $arguments Arguments for the task
381
     * @return void
382
     */
383
    private function generateNewUserStep50($taskData, $arguments) {
384
        // get user private key
385
        $ownerInfo = isset($arguments['owner_id']) && isset($arguments['creator_pwd']) 
386
            ? $this->getOwnerInfos($arguments['owner_id'], $arguments['creator_pwd']) 
387
            : null;
388
        $userInfo = $this->getOwnerInfos(
389
            $arguments['new_user_id'],
390
            $arguments['new_user_pwd'],
391
            ($arguments['only_personal_items'] ?? 0) === 1 ? 1 : 0,
392
            $arguments['new_user_private_key'] ?? ''
393
        );
394
395
        // Start transaction for better performance
396
        DB::startTransaction();
397
398
        // Loop on suggestions
399
        $rows = DB::query(
400
            'SELECT id
401
            FROM ' . prefixTable('suggestion') . '
402
            ORDER BY id ASC
403
            LIMIT %i, %i',
404
            $taskData['index'],
405
            $taskData['nb']
406
        );
407
        foreach ($rows as $record) {
408
            // Get itemKey from current user
409
            $currentUserKey = DB::queryFirstRow(
410
                'SELECT share_key
411
                FROM ' . prefixTable('sharekeys_suggestions') . '
412
                WHERE object_id = %i AND user_id = %i',
413
                $record['id'],
414
                $arguments['owner_id']
415
            );
416
417
            // do we have any input? (#3481)
418
            if ($currentUserKey === null || count($currentUserKey) === 0) {
419
                continue;
420
            }
421
422
            // Decrypt itemkey with admin key
423
            $itemKey = decryptUserObjectKey($currentUserKey['share_key'], $ownerInfo['private_key']);
424
425
            // Encrypt Item key
426
            $share_key_for_item = encryptUserObjectKey($itemKey, $userInfo['public_key']);
427
428
            // Save the key in DB
429
            insertOrUpdateSharekey(
430
                prefixTable('sharekeys_suggestions'),
431
                (int) $record['id'],
432
                (int) $arguments['new_user_id'],
433
                $share_key_for_item
434
            );
435
        }
436
437
        // Commit transaction
438
        DB::commit();
439
    }
440
441
442
    /**
443
     * Generate new user keys - step 60
444
     * @param array $taskData Task data
445
     * @param array $arguments Arguments for the task
446
     * @return void
447
     */
448
    private function generateNewUserStep60($taskData, $arguments) {
449
        // get user private key
450
        $ownerInfo = isset($arguments['owner_id']) && isset($arguments['creator_pwd']) 
451
            ? $this->getOwnerInfos($arguments['owner_id'], $arguments['creator_pwd']) 
452
            : null;
453
        $userInfo = $this->getOwnerInfos(
454
            $arguments['new_user_id'],
455
            $arguments['new_user_pwd'],
456
            ($arguments['only_personal_items'] ?? 0) === 1 ? 1 : 0,
457
            $arguments['new_user_private_key'] ?? ''
458
        );
459
460
        // Start transaction for better performance
461
        DB::startTransaction();
462
463
        // Loop on files
464
        $rows = DB::query(
465
            'SELECT f.id AS id, i.perso AS perso
466
            FROM ' . prefixTable('files') . ' AS f
467
            INNER JOIN ' . prefixTable('items') . ' AS i ON i.id = f.id_item
468
            WHERE f.status = "' . TP_ENCRYPTION_NAME . '"
469
            LIMIT %i, %i',
470
            $taskData['index'],
471
            $taskData['nb']
472
        ); //aes_encryption
473
        foreach ($rows as $record) {
474
            // Get itemKey from current user
475
            $currentUserKey = DB::queryFirstRow(
476
                'SELECT share_key, increment_id
477
                FROM ' . prefixTable('sharekeys_files') . '
478
                WHERE object_id = %i AND user_id = %i',
479
                $record['id'],
480
                (int) $record['perso'] === 0 ? $arguments['owner_id'] : $arguments['new_user_id']
481
            );
482
483
            // do we have any input? (#3481)
484
            if ($currentUserKey === null || count($currentUserKey) === 0) {
485
                continue;
486
            }
487
488
            // Decrypt itemkey with user key
489
            $itemKey = decryptUserObjectKey(
490
                $currentUserKey['share_key'],
491
                //$ownerInfo['private_key']
492
                (int) $record['perso'] === 0 ? $ownerInfo['private_key'] : $userInfo['private_key']
493
            );
494
            
495
            // Prevent to change key if its key is empty
496
            if (empty($itemKey) === true) {
497
                continue;
498
            }
499
500
            // Encrypt Item key
501
            $share_key_for_item = encryptUserObjectKey($itemKey, $userInfo['public_key']);
502
503
            // Save the key in DB
504
            insertOrUpdateSharekey(
505
                prefixTable('sharekeys_files'),
506
                (int) $record['id'],
507
                (int) $arguments['new_user_id'],
508
                $share_key_for_item
509
            );
510
        }
511
512
        // Commit transaction
513
        DB::commit();
514
    }
515
516
517
    /**
518
     * Generate new user keys - step 99
519
     * @param array $arguments Arguments for the task
520
     */
521
    private function generateNewUserStep99($arguments) {
522
        $lang = new Language('english');
523
524
        // IF USER IS NOT THE SAME
525
        if (isset($arguments['owner_id']) && (int) $arguments['new_user_id'] === (int) $arguments['owner_id']) {
526
            return [
527
                'new_index' => 0,
528
                'new_action' => 'finished',
529
            ];
530
        }
531
        
532
        // update LOG
533
        logEvents(
534
            $this->settings,
535
            'user_mngt',
536
            'at_user_new_keys',
537
            TP_USER_ID,
538
            "",
539
            (string) $arguments['new_user_id']
540
        );
541
542
        // Personal items encryption only?
543
        if (($arguments['only_personal_items'] ?? 0) === 1) {
544
            // Set user as ready for usage
545
            DB::update(
546
                prefixTable('users'),
547
                array(
548
                    'ongoing_process_id' => NULL,
549
                    'special' => 'none',
550
                    'updated_at' => time(),
551
                ),
552
                'id = %i',
553
                $arguments['new_user_id']
554
            );
555
            return;
556
        }
557
558
        // if done then send email to new user
559
        // get user info
560
        $userInfo = DB::queryFirstRow(
561
            'SELECT u.email, u.login, u.auth_type, u.special, u.lastname, u.name
562
            FROM ' . prefixTable('users') . ' AS u
563
            WHERE u.id = %i',
564
            $arguments['new_user_id']
565
        );
566
567
        // SEND EMAIL TO USER depending on context
568
        // Config 1: new user is a local user
569
        // Config 2: new user is an LDAP user
570
        // Config 3: send new password
571
        // COnfig 4: send new encryption code
572
        if (isset($arguments['send_email']) === true && (int) $arguments['send_email'] === 1 && !empty($userInfo['email'])) {
573
            sendMailToUser(
574
                filter_var($userInfo['email'], FILTER_SANITIZE_EMAIL),
575
                // @scrutinizer ignore-type
576
                empty($arguments['email_body']) === false ? $arguments['email_body'] : $lang->get('email_body_user_config_1'),
577
                'TEAMPASS - ' . $lang->get('login_credentials'),
578
                (array) filter_var_array(
579
                    [
580
                        '#code#' => cryption($arguments['new_user_code'], '','decrypt', $this->settings)['string'],
581
                        '#lastname#' => isset($userInfo['name']) === true ? $userInfo['name'] : '',
582
                        '#login#' => isset($userInfo['login']) === true ? $userInfo['login'] : '',
583
                    ],
584
                    FILTER_SANITIZE_FULL_SPECIAL_CHARS
585
                ),
586
                false,
587
                $arguments['new_user_pwd']
588
            );
589
        }
590
591
        /*
592
        // Does user has personal items?
593
        $personalItemsCount = DB::queryFirstField(
594
            'SELECT COUNT(*)
595
            FROM ' . prefixTable('items') . '
596
            WHERE perso = 1 AND id IN (SELECT object_id FROM ' . prefixTable('sharekeys_items') . ' WHERE user_id = %i)',
597
            $arguments['new_user_id']
598
        );
599
600
        // Set user as ready for usage
601
        DB::update(
602
            prefixTable('users'),
603
            array(
604
                'is_ready_for_usage' => 1,
605
                'otp_provided' => isset($arguments['otp_provided_new_value']) === true && (int) $arguments['otp_provided_new_value'] === 1 ? $arguments['otp_provided_new_value'] : 0,
606
                'ongoing_process_id' => NULL,
607
                'special' => $personalItemsCount > 0 ? 'encrypt_personal_items' : 'none',
608
                'updated_at' => time(),
609
            ),
610
            'id = %i',
611
            $arguments['new_user_id']
612
        );
613
        */
614
615
        // if special status is generate-keys, then set it to none
616
        if (isset($userInfo['special']) === true && $userInfo['special'] === 'generate-keys') {
617
            DB::update(
618
                prefixTable('users'),
619
                array(
620
                    'is_ready_for_usage' => 1,
621
                    'otp_provided' => isset($arguments['otp_provided_new_value']) === true && (int) $arguments['otp_provided_new_value'] === 1 ? $arguments['otp_provided_new_value'] : 0,
622
                    'ongoing_process_id' => NULL,
623
                    'special' => isset($arguments['userHasToEncryptPersonalItemsAfter']) === true && (int) $arguments['userHasToEncryptPersonalItemsAfter'] === 1 ? 'encrypt_personal_items_with_new_password' : 'none',
624
                    'updated_at' => time(),
625
                ),
626
                'id = %i',
627
                $arguments['new_user_id']
628
            );
629
        }
630
    }
631
    
632
633
    /**
634
     * Get owner info
635
     * @param int $owner_id Owner ID
636
     * @param string $owner_pwd Owner password
637
     * @param int $only_personal_items 1 if only personal items, 0 else
638
     * @param string $owner_pwd Owner password
639
     * @return array Owner information
640
     */
641
    private function getOwnerInfos(int $owner_id, string $owner_pwd, ?int $only_personal_items = 0, ?string $owner_private_key = ''): array {
642
        $userInfo = DB::queryFirstRow(
643
            'SELECT pw, public_key, private_key, login, name
644
            FROM ' . prefixTable('users') . '
645
            WHERE id = %i',
646
            $owner_id
647
        );
648
649
        // decrypt owner password 
650
        $pwd = cryption($owner_pwd, '','decrypt', $this->settings)['string'];
651
652
        // decrypt private key and send back
653
        if ((int) $only_personal_items === 1 && empty($owner_private_key) === false) {
654
            // Explicitely case where we only want personal items and where user has provided his private key
655
            return [
656
                'private_key' => cryption($owner_private_key, '','decrypt')['string'],
657
                'public_key' => $userInfo['public_key'],
658
                'login' => $userInfo['login'],
659
                'name' => $userInfo['name'],
660
            ];
661
        }else {
662
            // Normal case
663
            return [
664
                'private_key' => decryptPrivateKey($pwd, $userInfo['private_key']),
665
                'public_key' => $userInfo['public_key'],
666
                'login' => $userInfo['login'],
667
                'name' => $userInfo['name'],
668
            ];
669
        }
670
    }
671
}