Passed
Pull Request — master (#4676)
by Nils
05:55
created

UserHandlerTrait::processGenerateUserKeysSubtask()   B

Complexity

Conditions 10
Paths 49

Size

Total Lines 71
Code Lines 52

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 10
eloc 52
c 2
b 0
f 0
nc 49
nop 2
dl 0
loc 71
rs 7.1806

How to fix   Long Method    Complexity   

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
            deleteUserObjetsKeys($arguments['new_user_id'], $this->settings);
169
        }
170
    }
171
172
173
    /**
174
     * Generate new user keys
175
     * @param array $taskData Task data
176
     * @param array $arguments Arguments for the task
177
     */
178
    private function generateNewUserStep20($taskData, $arguments) {
179
        // get user private key
180
        $ownerInfo = $this->getOwnerInfos($arguments['owner_id'], $arguments['creator_pwd']);
181
        $userInfo = $this->getOwnerInfos($arguments['new_user_id'], $arguments['new_user_pwd']);
182
        
183
        // Start transaction for better performance
184
        DB::startTransaction();
185
186
        // Loop on items
187
        $rows = DB::query(
188
            'SELECT id, pw, perso
189
            FROM ' . prefixTable('items') . '
190
            WHERE perso =  %i
191
            ORDER BY id ASC
192
            LIMIT ' . $taskData['index'] . ', ' . $taskData['nb'],
193
            ($arguments['only_personal_items'] ?? 0) === 1 ? 1 : 0
194
        );
195
196
        foreach ($rows as $record) {
197
            // Get itemKey from current user
198
            $currentUserKey = DB::queryFirstRow(
199
                'SELECT share_key, increment_id
200
                FROM ' . prefixTable('sharekeys_items') . '
201
                WHERE object_id = %i AND user_id = %i',
202
                $record['id'],
203
                (int) $record['perso'] === 0 ? $arguments['owner_id'] : $arguments['new_user_id']
204
            );
205
206
            // do we have any input? (#3481)
207
            if ($currentUserKey === null || count($currentUserKey) === 0) {
208
                continue;
209
            }
210
211
            // Decrypt itemkey with admin key
212
            $itemKey = decryptUserObjectKey(
213
                $currentUserKey['share_key'],
214
                (int) $record['perso'] === 0 ? $ownerInfo['private_key'] : $userInfo['private_key']
215
            );
216
            
217
            // Prevent to change key if its key is empty
218
            if (empty($itemKey) === true) {
219
                $share_key_for_item = '';
220
            } else {
221
                // Encrypt Item key
222
                $share_key_for_item = encryptUserObjectKey($itemKey, $userInfo['public_key']);
223
            }
224
            
225
            $currentUserKey = DB::queryFirstRow(
226
                'SELECT increment_id
227
                FROM ' . prefixTable('sharekeys_items') . '
228
                WHERE object_id = %i AND user_id = %i',
229
                $record['id'],
230
                $arguments['new_user_id']
231
            );
232
233
            if ($currentUserKey) {
234
                // NOw update
235
                DB::update(
236
                    prefixTable('sharekeys_items'),
237
                    array(
238
                        'share_key' => $share_key_for_item,
239
                    ),
240
                    'increment_id = %i',
241
                    $currentUserKey['increment_id']
242
                );
243
            } else {
244
                DB::insert(
245
                    prefixTable('sharekeys_items'),
246
                    array(
247
                        'object_id' => (int) $record['id'],
248
                        'user_id' => (int) $arguments['new_user_id'],
249
                        'share_key' => $share_key_for_item,
250
                    )
251
                );
252
            }
253
        }
254
255
        // Commit transaction
256
        DB::commit();
257
    }
258
259
260
    /**
261
     * Generate new user keys - step 30
262
     * @param array $taskData Task data
263
     * @param array $arguments Arguments for the task
264
     * @return void
265
     */
266
    private function generateNewUserStep30($taskData, $arguments) {
267
        // get user private key
268
        $ownerInfo = $this->getOwnerInfos($arguments['owner_id'], $arguments['creator_pwd']);
269
        $userInfo = $this->getOwnerInfos($arguments['new_user_id'], $arguments['new_user_pwd']);
270
271
        // Start transaction for better performance
272
        DB::startTransaction();
273
274
        // Loop on logs
275
        $rows = DB::query(
276
            'SELECT increment_id
277
            FROM ' . prefixTable('log_items') . '
278
            WHERE raison LIKE "at_pw :%" AND encryption_type = "teampass_aes"
279
            ORDER BY increment_id ASC
280
            LIMIT ' . $taskData['index'] . ', ' . $taskData['nb']
281
        );
282
        foreach ($rows as $record) {
283
            // Get itemKey from current user
284
            $currentUserKey = DB::queryFirstRow(
285
                'SELECT share_key
286
                FROM ' . prefixTable('sharekeys_logs') . '
287
                WHERE object_id = %i AND user_id = %i',
288
                $record['increment_id'],
289
                $arguments['owner_id']
290
            );
291
292
            // do we have any input? (#3481)
293
            if ($currentUserKey === null || count($currentUserKey) === 0) {
294
                continue;
295
            }
296
297
            // Decrypt itemkey with admin key
298
            $itemKey = decryptUserObjectKey($currentUserKey['share_key'], $ownerInfo['private_key']);
299
300
            // Encrypt Item key
301
            $share_key_for_item = encryptUserObjectKey($itemKey, $userInfo['public_key']);
302
303
            // Save the key in DB
304
            if ($arguments['user_self_change'] === false) {
305
                DB::insert(
306
                    prefixTable('sharekeys_logs'),
307
                    array(
308
                        'object_id' => (int) $record['increment_id'],
309
                        'user_id' => (int) $arguments['new_user_id'],
310
                        'share_key' => $share_key_for_item,
311
                    )
312
                );
313
            } else {
314
                // Get itemIncrement from selected user
315
                if ((int) $arguments['new_user_id'] !== (int) $arguments['owner_id']) {
316
                    $currentUserKey = DB::queryFirstRow(
317
                        'SELECT increment_id
318
                        FROM ' . prefixTable('sharekeys_items') . '
319
                        WHERE object_id = %i AND user_id = %i',
320
                        $record['id'],
321
                        $arguments['new_user_id']
322
                    );
323
                }
324
325
                // NOw update
326
                DB::update(
327
                    prefixTable('sharekeys_logs'),
328
                    array(
329
                        'share_key' => $share_key_for_item,
330
                    ),
331
                    'increment_id = %i',
332
                    $currentUserKey['increment_id']
333
                );
334
            }
335
        }
336
337
        // Commit transaction
338
        DB::commit();
339
    }
340
341
342
    /**
343
     * Generate new user keys - step 40
344
     * @param array $taskData Task data
345
     * @param array $arguments Arguments for the task
346
     * @return void
347
     */
348
    private function generateNewUserStep40($taskData, $arguments) {
349
        // get user private key
350
        $ownerInfo = $this->getOwnerInfos($arguments['owner_id'], $arguments['creator_pwd']);
351
        $userInfo = $this->getOwnerInfos($arguments['new_user_id'], $arguments['new_user_pwd']);
352
353
        // Start transaction for better performance
354
        DB::startTransaction();
355
356
        // Loop on fields
357
        $rows = DB::query(
358
            'SELECT id
359
            FROM ' . prefixTable('categories_items') . '
360
            WHERE encryption_type = "teampass_aes"
361
            ORDER BY id ASC
362
            LIMIT ' . $taskData['index'] . ', ' . $taskData['nb']
363
        );
364
        foreach ($rows as $record) {
365
            // Get itemKey from current user
366
            $currentUserKey = DB::queryFirstRow(
367
                'SELECT share_key
368
                FROM ' . prefixTable('sharekeys_fields') . '
369
                WHERE object_id = %i AND user_id = %i',
370
                $record['id'],
371
                $arguments['owner_id']
372
            );
373
374
            if (isset($currentUserKey['share_key']) === true) {
375
                // Decrypt itemkey with admin key
376
                $itemKey = decryptUserObjectKey($currentUserKey['share_key'], $ownerInfo['private_key']);
377
378
                // Encrypt Item key
379
                $share_key_for_item = encryptUserObjectKey($itemKey, $userInfo['public_key']);
380
381
                // Save the key in DB
382
                if ($arguments['user_self_change'] === false) {
383
                    DB::insert(
384
                        prefixTable('sharekeys_fields'),
385
                        array(
386
                            'object_id' => (int) $record['id'],
387
                            'user_id' => (int) $arguments['new_user_id'],
388
                            'share_key' => $share_key_for_item,
389
                        )
390
                    );
391
                } else {
392
                    // Get itemIncrement from selected user
393
                    if ((int) $arguments['new_user_id'] !== (int) $arguments['owner_id']) {
394
                        $currentUserKey = DB::queryFirstRow(
395
                            'SELECT increment_id
396
                            FROM ' . prefixTable('sharekeys_items') . '
397
                            WHERE object_id = %i AND user_id = %i',
398
                            $record['id'],
399
                            $arguments['new_user_id']
400
                        );
401
                    }
402
403
                    // NOw update
404
                    DB::update(
405
                        prefixTable('sharekeys_fields'),
406
                        array(
407
                            'share_key' => $share_key_for_item,
408
                        ),
409
                        'increment_id = %i',
410
                        $currentUserKey['increment_id']
411
                    );
412
                }
413
            }
414
        }
415
416
        // Commit transaction
417
        DB::commit();
418
    }
419
420
421
    /**
422
     * Generate new user keys - step 50
423
     * @param array $taskData Task data
424
     * @param array $arguments Arguments for the task
425
     * @return void
426
     */
427
    private function generateNewUserStep50($taskData, $arguments) {
428
        // get user private key
429
        $ownerInfo = $this->getOwnerInfos($arguments['owner_id'], $arguments['creator_pwd']);
430
        $userInfo = $this->getOwnerInfos($arguments['new_user_id'], $arguments['new_user_pwd']);
431
432
        // Start transaction for better performance
433
        DB::startTransaction();
434
435
        // Loop on suggestions
436
        $rows = DB::query(
437
            'SELECT id
438
            FROM ' . prefixTable('suggestion') . '
439
            ORDER BY id ASC
440
            LIMIT ' . $taskData['index'] . ', ' . $taskData['nb']
441
        );
442
        foreach ($rows as $record) {
443
            // Get itemKey from current user
444
            $currentUserKey = DB::queryFirstRow(
445
                'SELECT share_key
446
                FROM ' . prefixTable('sharekeys_suggestions') . '
447
                WHERE object_id = %i AND user_id = %i',
448
                $record['id'],
449
                $arguments['owner_id']
450
            );
451
452
            // do we have any input? (#3481)
453
            if ($currentUserKey === null || count($currentUserKey) === 0) {
454
                continue;
455
            }
456
457
            // Decrypt itemkey with admin key
458
            $itemKey = decryptUserObjectKey($currentUserKey['share_key'], $ownerInfo['private_key']);
459
460
            // Encrypt Item key
461
            $share_key_for_item = encryptUserObjectKey($itemKey, $userInfo['public_key']);
462
463
            // Save the key in DB
464
            if ($arguments['user_self_change'] === false) {
465
                DB::insert(
466
                    prefixTable('sharekeys_suggestions'),
467
                    array(
468
                        'object_id' => (int) $record['id'],
469
                        'user_id' => (int) $arguments['new_user_id'],
470
                        'share_key' => $share_key_for_item,
471
                    )
472
                );
473
            } else {
474
                // Get itemIncrement from selected user
475
                if ((int) $arguments['new_user_id'] !== (int) $arguments['owner_id']) {
476
                    $currentUserKey = DB::queryFirstRow(
477
                        'SELECT increment_id
478
                        FROM ' . prefixTable('sharekeys_items') . '
479
                        WHERE object_id = %i AND user_id = %i',
480
                        $record['id'],
481
                        $arguments['new_user_id']
482
                    );
483
                }
484
485
                // NOw update
486
                DB::update(
487
                    prefixTable('sharekeys_suggestions'),
488
                    array(
489
                        'share_key' => $share_key_for_item,
490
                    ),
491
                    'increment_id = %i',
492
                    $currentUserKey['increment_id']
493
                );
494
            }
495
        }
496
497
        // Commit transaction
498
        DB::commit();
499
    }
500
501
502
    /**
503
     * Generate new user keys - step 60
504
     * @param array $taskData Task data
505
     * @param array $arguments Arguments for the task
506
     * @return void
507
     */
508
    private function generateNewUserStep60($taskData, $arguments) {
509
        // get user private key
510
        $ownerInfo = $this->getOwnerInfos($arguments['owner_id'], $arguments['creator_pwd']);
511
        $userInfo = $this->getOwnerInfos($arguments['new_user_id'], $arguments['new_user_pwd']);
512
513
        // Start transaction for better performance
514
        DB::startTransaction();
515
516
        // Loop on files
517
        $rows = DB::query(
518
            'SELECT f.id AS id, i.perso AS perso
519
            FROM ' . prefixTable('files') . ' AS f
520
            INNER JOIN ' . prefixTable('items') . ' AS i ON i.id = f.id_item
521
            WHERE f.status = "' . TP_ENCRYPTION_NAME . '"
522
            LIMIT ' . $taskData['index'] . ', ' . $taskData['nb']
523
        ); //aes_encryption
524
        foreach ($rows as $record) {
525
            // Get itemKey from current user
526
            $currentUserKey = DB::queryFirstRow(
527
                'SELECT share_key, increment_id
528
                FROM ' . prefixTable('sharekeys_files') . '
529
                WHERE object_id = %i AND user_id = %i',
530
                $record['id'],
531
                (int) $record['perso'] === 0 ? $arguments['owner_id'] : $arguments['new_user_id']
532
            );
533
534
            // do we have any input? (#3481)
535
            if ($currentUserKey === null || count($currentUserKey) === 0) {
536
                continue;
537
            }
538
539
            // Decrypt itemkey with user key
540
            $itemKey = decryptUserObjectKey(
541
                $currentUserKey['share_key'],
542
                //$ownerInfo['private_key']
543
                (int) $record['perso'] === 0 ? $ownerInfo['private_key'] : $userInfo['private_key']
544
            );
545
            
546
            // Prevent to change key if its key is empty
547
            if (empty($itemKey) === true) {
548
                continue;
549
            }
550
551
            // Encrypt Item key
552
            $share_key_for_item = encryptUserObjectKey($itemKey, $userInfo['public_key']);
553
554
            $currentUserKey = DB::queryFirstRow(
555
                'SELECT increment_id
556
                FROM ' . prefixTable('sharekeys_files') . '
557
                WHERE object_id = %i AND user_id = %i',
558
                $record['id'],
559
                $arguments['new_user_id']
560
            );
561
            // Save the key in DB
562
            if (DB::count() > 0) {
563
                // NOw update
564
                DB::update(
565
                    prefixTable('sharekeys_files'),
566
                    array(
567
                        'share_key' => $share_key_for_item,
568
                    ),
569
                    'increment_id = %i',
570
                    $currentUserKey['increment_id']
571
                );
572
            } else {
573
                DB::insert(
574
                    prefixTable('sharekeys_files'),
575
                    array(
576
                        'object_id' => (int) $record['id'],
577
                        'user_id' => (int) $arguments['new_user_id'],
578
                        'share_key' => $share_key_for_item,
579
                    )
580
                );
581
            }
582
        }
583
584
        // Commit transaction
585
        DB::commit();
586
    }
587
588
589
    /**
590
     * Generate new user keys - step 99
591
     * @param array $arguments Arguments for the task
592
     */
593
    private function generateNewUserStep99($arguments) {
594
        $lang = new Language('english');
595
596
        // IF USER IS NOT THE SAME
597
        if ((int) $arguments['new_user_id'] === (int) $arguments['owner_id']) {
598
            return [
599
                'new_index' => 0,
600
                'new_action' => 'finished',
601
            ];
602
        }
603
        
604
        // update LOG
605
        logEvents(
606
            $this->settings,
607
            'user_mngt',
608
            'at_user_new_keys',
609
            TP_USER_ID,
610
            "",
611
            (string) $arguments['new_user_id']
612
        );
613
614
        // if done then send email to new user
615
        // get user info
616
        $userInfo = DB::queryFirstRow(
617
            'SELECT email, login, auth_type, special, lastname, name
618
            FROM ' . prefixTable('users') . '
619
            WHERE id = %i',
620
            $arguments['new_user_id']
621
        );
622
623
        // SEND EMAIL TO USER depending on context
624
        // Config 1: new user is a local user
625
        // Config 2: new user is an LDAP user
626
        // Config 3: send new password
627
        // COnfig 4: send new encryption code
628
        if (isset($arguments['send_email']) === true && (int) $arguments['send_email'] === 1) {
629
            sendMailToUser(
630
                filter_var($userInfo['email'], FILTER_SANITIZE_FULL_SPECIAL_CHARS),
631
                // @scrutinizer ignore-type
632
                empty($arguments['email_body']) === false ? $arguments['email_body'] : $lang->get('email_body_user_config_1'),
633
                'TEAMPASS - ' . $lang->get('login_credentials'),
634
                (array) filter_var_array(
635
                    [
636
                        '#code#' => cryption($arguments['new_user_code'], '','decrypt', $this->settings)['string'],
637
                        '#lastname#' => isset($userInfo['name']) === true ? $userInfo['name'] : '',
638
                        '#login#' => isset($userInfo['login']) === true ? $userInfo['login'] : '',
639
                    ],
640
                    FILTER_SANITIZE_FULL_SPECIAL_CHARS
641
                ),
642
                false,
643
                $arguments['new_user_pwd']
644
            );
645
        }
646
            
647
        // Set user as ready for usage
648
        DB::update(
649
            prefixTable('users'),
650
            array(
651
                'is_ready_for_usage' => 1,
652
                'otp_provided' => isset($arguments['otp_provided_new_value']) === true && (int) $arguments['otp_provided_new_value'] === 1 ? $arguments['otp_provided_new_value'] : 0,
653
                'ongoing_process_id' => NULL,
654
                'special' => 'none',
655
                'updated_at' => time(),
656
            ),
657
            'id = %i',
658
            $arguments['new_user_id']
659
        );
660
    }
661
    
662
663
    /**
664
     * Get owner info
665
     * @param int $owner_id Owner ID
666
     * @param string $owner_pwd Owner password
667
     * @return array Owner information
668
     */
669
    private function getOwnerInfos(int $owner_id, string $owner_pwd) {
670
        $userInfo = DB::queryFirstRow(
671
            'SELECT pw, public_key, private_key, login, name
672
            FROM ' . prefixTable('users') . '
673
            WHERE id = %i',
674
            $owner_id
675
        );
676
677
        // decrypt owner password
678
        $pwd = cryption($owner_pwd, '','decrypt', $this->settings)['string'];
679
        // decrypt private key and send back
680
        return [
681
            'private_key' => decryptPrivateKey($pwd, $userInfo['private_key']),
682
            'public_key' => $userInfo['public_key'],
683
            'login' => $userInfo['login'],
684
            'name' => $userInfo['name'],
685
        ];
686
    }
687
}