UserHandlerTrait::processGenerateUserKeysSubtask()   B
last analyzed

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