UserHandlerTrait   F
last analyzed

Complexity

Total Complexity 63

Size/Duplication

Total Lines 662
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 321
dl 0
loc 662
rs 3.36
c 2
b 0
f 0
wmc 63

11 Methods

Rating   Name   Duplication   Size   Complexity  
A handleUserBuildCacheTree() 0 2 1
A generateUserKeys() 0 25 6
A generateNewUserStep0() 0 4 2
B processGenerateUserKeysSubtask() 0 71 10
B generateNewUserStep99() 0 66 9
B generateNewUserStep50() 0 74 6
A getOwnerInfos() 0 16 1
A generateNewUserStep40() 0 72 5
B generateNewUserStep20() 0 81 9
B generateNewUserStep30() 0 73 6
B generateNewUserStep60() 0 80 8

How to fix   Complexity   

Complex Class

Complex classes like UserHandlerTrait often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use UserHandlerTrait, and based on these observations, apply Extract Interface, too.

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