Passed
Push — master ( e7d28b...261004 )
by Nils
06:20
created

listDeletedUsers()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 1
eloc 8
c 1
b 1
f 0
nc 1
nop 0
dl 0
loc 15
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * Teampass - a collaborative passwords manager.
7
 * ---
8
 * This file is part of the TeamPass project.
9
 * 
10
 * TeamPass is free software: you can redistribute it and/or modify it
11
 * under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation, version 3 of the License.
13
 * 
14
 * TeamPass is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU General Public License for more details.
18
 * 
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21
 * 
22
 * Certain components of this file may be under different licenses. For
23
 * details, see the `licenses` directory or individual file headers.
24
 * ---
25
 * @file      users.queries.php
26
 * @author    Nils Laumaillé ([email protected])
27
 * @copyright 2009-2025 Teampass.net
28
 * @license   GPL-3.0
29
 * @see       https://www.teampass.net
30
 */
31
32
use LdapRecord\Connection;
33
use TeampassClasses\NestedTree\NestedTree;
34
use TeampassClasses\SessionManager\SessionManager;
35
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
36
use TeampassClasses\Language\Language;
37
use TeampassClasses\PerformChecks\PerformChecks;
38
use TeampassClasses\ConfigManager\ConfigManager;
39
use TeampassClasses\PasswordManager\PasswordManager;
40
use TeampassClasses\EmailService\EmailService;
41
use TeampassClasses\EmailService\EmailSettings;
42
use TeampassClasses\OAuth2Controller\OAuth2Controller;
43
44
// Load functions
45
require_once 'main.functions.php';
46
47
// init
48
loadClasses('DB');
49
$session = SessionManager::getSession();
50
$request = SymfonyRequest::createFromGlobals();
51
$lang = new Language($session->get('user-language') ?? 'english');
52
53
// Load config
54
$configManager = new ConfigManager();
55
$SETTINGS = $configManager->getAllSettings();
56
57
// Do checks
58
$checkUserAccess = new PerformChecks(
59
    dataSanitizer(
60
        [
61
            'type' => htmlspecialchars($request->request->get('type', ''), ENT_QUOTES, 'UTF-8'),
62
        ],
63
        [
64
            'type' => 'trim|escape',
65
        ],
66
    ),
67
    [
68
        'user_id' => returnIfSet($session->get('user-id'), null),
69
        'user_key' => returnIfSet($session->get('key'), null),
70
    ]
71
);
72
// Handle the case
73
echo $checkUserAccess->caseHandler();
74
if ($checkUserAccess->checkSession() === false || $checkUserAccess->userAccessPage('profile') === false) {
75
    // Not allowed page
76
    $session->set('system-error_code', ERR_NOT_ALLOWED);
77
    include $SETTINGS['cpassman_dir'] . '/error.php';
78
    exit;
79
}
80
81
// Define Timezone
82
date_default_timezone_set($SETTINGS['timezone'] ?? 'UTC');
83
84
// Set header properties
85
header('Content-type: text/html; charset=utf-8');
86
header('Cache-Control: no-cache, no-store, must-revalidate');
87
88
// --------------------------------- //
89
90
// Prepare post variables
91
$post_key = filter_input(INPUT_POST, 'key', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
92
$post_type = filter_input(INPUT_POST, 'type', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
93
$post_data = filter_input(INPUT_POST, 'data', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_FLAG_NO_ENCODE_QUOTES);
94
$isprofileupdate = filter_input(INPUT_POST, 'isprofileupdate', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
95
$password_do_not_change = 'do_not_change';
96
97
98
//Load Tree
99
$tree = new NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
100
101
if (null !== $post_type) {
102
103
    // List of post types allowed to all users
104
    $all_users_can_access = [
105
        'get_generate_keys_progress',
106
        'user_profile_update',
107
        'save_user_change',
108
    ];
109
110
    // decrypt and retrieve data in JSON format
111
    $dataReceived = [];
112
    if (!empty($post_data)) {
113
        $dataReceived = prepareExchangedData(
114
            $post_data,
115
            'decode'
116
        );
117
    }
118
119
    // Non-manager user
120
    if ((int) $session->get('user-admin') !== 1 &&
121
        (int) $session->get('user-manager') !== 1 &&
122
        (int) $session->get('user-can_manage_all_users') !== 1) {
123
124
        // Administrative type requested -> deny
125
        if (!in_array($post_type, $all_users_can_access)) {
126
            echo prepareExchangedData(
127
                array(
128
                    'error' => true,
129
                    'message' => $lang->get('error_not_allowed_to'),
130
                ),
131
                'encode'
132
            );
133
            exit;
134
        } else if (isset($dataReceived['user_id'])) {
135
            // If user isn't manager, he can't change user_id
136
            $dataReceived['user_id'] = (int) $session->get('user-id');
137
        }
138
    }
139
140
    // For administrative types only, do additional check whether user is manager 
141
    // and $dataReceived['user_id'] is defined to ensure that this manager can
142
    // modify this user account.
143
    if (!in_array($post_type, $all_users_can_access) &&
144
        (int) $session->get('user-admin') !== 1 && !empty($dataReceived['user_id'])) {
145
146
        // Get info about user to modify
147
        $targetUserInfos = DB::queryFirstRow(
148
            'SELECT admin, gestionnaire, can_manage_all_users, isAdministratedByRole FROM ' . prefixTable('users') . '
149
            WHERE id = %i',
150
            (int) $dataReceived['user_id']
151
        );
152
153
        // User not exists
154
        if (DB::count() === 0) {
155
            echo prepareExchangedData(
156
                array(
157
                    'error' => true,
158
                    'message' => $lang->get('error_not_allowed_to'),
159
                ),
160
                'encode'
161
            );
162
            exit;
163
        }
164
165
        // Managers can't edit administrator or other manager
166
        if ((int) $targetUserInfos['admin'] === 1 ||
167
            (int) $targetUserInfos['can_manage_all_users'] === 1 ||
168
            (int) $targetUserInfos['gestionnaire'] === 1) {
169
170
                echo prepareExchangedData(
171
                    array(
172
                        'error' => true,
173
                        'message' => $lang->get('error_not_allowed_to'),
174
                    ),
175
                    'encode'
176
                );
177
                exit;
178
            }
179
180
        // Manager of basic/ro users in this role
181
        if ((int) $session->get('user-manager') === 1
182
            && !in_array($targetUserInfos['isAdministratedByRole'], $session->get('user-roles_array'))) {
183
184
            echo prepareExchangedData(
185
                array(
186
                    'error' => true,
187
                    'message' => $lang->get('error_not_allowed_to'),
188
                ),
189
                'encode'
190
            );
191
            exit;
192
        }
193
    }
194
195
    switch ($post_type) {
196
        /*
197
         * ADD NEW USER
198
         */
199
        case 'add_new_user':
200
            // Check KEY
201
            if ($post_key !== $session->get('key')) {
202
                echo prepareExchangedData(
203
                    array(
204
                        'error' => true,
205
                        'message' => $lang->get('key_is_not_correct'),
206
                    ),
207
                    'encode'
208
                );
209
                break;
210
            } elseif ($session->get('user-read_only') === 1) {
211
                echo prepareExchangedData(
212
                    array(
213
                        'error' => true,
214
                        'message' => $lang->get('error_not_allowed_to'),
215
                    ),
216
                    'encode'
217
                );
218
                break;
219
            }
220
221
            // Check if current user can add a new user
222
            if ((int) $session->get('user-admin') === 0 && (int) $session->get('user-can_manage_all_users') === 0 && (int) $session->get('user-manager') === 0) {
223
                echo prepareExchangedData(
224
                    array(
225
                        'error' => true,
226
                        'message' => $lang->get('error_not_allowed_to'),
227
                    ),
228
                    'encode'
229
                );
230
                break;
231
            }
232
233
            // Prepare variables
234
            $login = filter_var($dataReceived['login'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
235
            $email = filter_var($dataReceived['email'], FILTER_SANITIZE_EMAIL);
236
            $lastname = filter_var($dataReceived['lastname'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
237
            $name = filter_var($dataReceived['name'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
238
            $is_admin = filter_var($dataReceived['admin'], FILTER_SANITIZE_NUMBER_INT);
239
            $is_manager = filter_var($dataReceived['manager'], FILTER_SANITIZE_NUMBER_INT);
240
            $is_hr = filter_var($dataReceived['hr'], FILTER_SANITIZE_NUMBER_INT);
241
            $is_read_only = filter_var($dataReceived['read_only'], FILTER_SANITIZE_NUMBER_INT) || 0;
242
            $has_personal_folder = filter_var($dataReceived['personal_folder'], FILTER_SANITIZE_NUMBER_INT);
243
            $new_folder_role_domain = filter_var($dataReceived['new_folder_role_domain'], FILTER_SANITIZE_NUMBER_INT);
244
            $domain = filter_var($dataReceived['domain'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
245
            $is_administrated_by = filter_var($dataReceived['isAdministratedByRole'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
246
            $groups = filter_var_array($dataReceived['groups'], FILTER_SANITIZE_NUMBER_INT);
247
            $allowed_flds = filter_var_array($dataReceived['allowed_flds'], FILTER_SANITIZE_NUMBER_INT);
248
            $forbidden_flds = filter_var_array($dataReceived['forbidden_flds'], FILTER_SANITIZE_NUMBER_INT);
249
            $post_root_level = filter_var($dataReceived['form-create-root-folder'], FILTER_SANITIZE_NUMBER_INT);
250
            $mfa_enabled = filter_var($dataReceived['mfa_enabled'], FILTER_SANITIZE_NUMBER_INT);
251
252
            // Only administrators can create managers or administrators accounts.
253
            if ((int) $session->get('user-admin') !== 1 
254
                && ((int) $is_admin === 1 || (int) $is_manager === 1 || (int) $is_hr === 1)) {
255
256
                echo prepareExchangedData(
257
                    array(
258
                        'error' => true,
259
                        'message' => $lang->get('error_not_allowed_to'),
260
                    ),
261
                    'encode'
262
                );
263
                break;
264
            }
265
266
            // Empty user
267
            if (empty($login) === true) {
268
                echo prepareExchangedData(
269
                    array(
270
                        'error' => true,
271
                        'message' => $lang->get('error_empty_data'),
272
                    ),
273
                    'encode'
274
                );
275
                break;
276
            }
277
            // Check if user already exists
278
            $data = DB::query(
279
                'SELECT id, fonction_id, groupes_interdits, groupes_visibles
280
                FROM ' . prefixTable('users') . '
281
                WHERE login = %s
282
                AND deleted_at IS NULL',
283
                $login
284
            );
285
286
            if (DB::count() === 0) {
287
                // Generate pwd
288
                $password = generateQuickPassword();
289
290
                // Generate new keys with transparent recovery support
291
                $userKeys = generateUserKeys($password, $SETTINGS);
292
293
                // load password library
294
                $passwordManager = new PasswordManager();
295
296
                // Prepare variables
297
                $hashedPassword = $passwordManager->hashPassword($password);
298
                if ($passwordManager->verifyPassword($hashedPassword, $password) === false) {
299
                    echo prepareExchangedData(
300
                        array(
301
                            'error' => true,
302
                            'message' => $lang->get('pw_hash_not_correct'),
303
                        ),
304
                        'encode'
305
                    );
306
                    break;
307
                }
308
309
                // Add user in DB
310
                DB::insert(
311
                    prefixTable('users'),
312
                    array(
313
                        'login' => $login,
314
                        'name' => $name,
315
                        'lastname' => $lastname,
316
                        'pw' => $hashedPassword,
317
                        'email' => $email,
318
                        'admin' => empty($is_admin) === true ? 0 : $is_admin,
319
                        'can_manage_all_users' => empty($is_hr) === true ? 0 : $is_hr,
320
                        'gestionnaire' => empty($is_manager) === true ? 0 : $is_manager,
321
                        'read_only' => empty($is_read_only) === true ? 0 : $is_read_only,
322
                        'personal_folder' => empty($has_personal_folder) === true ? 0 : $has_personal_folder,
323
                        'user_language' => $SETTINGS['default_language'],
324
                        'fonction_id' => is_null($groups) === true ? '' : implode(';', $groups),
325
                        'groupes_interdits' => is_null($forbidden_flds) === true ? '' : implode(';', $forbidden_flds),
326
                        'groupes_visibles' => is_null($allowed_flds) === true ? '' : implode(';', $allowed_flds),
327
                        'isAdministratedByRole' => $is_administrated_by,
328
                        'encrypted_psk' => '',
329
                        'last_pw_change' => time(),
330
                        'public_key' => $userKeys['public_key'],
331
                        'private_key' => $userKeys['private_key'],
332
                        'special' => 'auth-pwd-change',
333
                        'is_ready_for_usage' => 0,
334
                        'otp_provided' => 0,
335
                        'can_create_root_folder' => empty($post_root_level) === true ? 0 : $post_root_level,
336
                        'mfa_enabled' => empty($mfa_enabled) === true ? 0 : $mfa_enabled,
337
                        'created_at' => time(),
338
                    )
339
                );
340
                $new_user_id = DB::insertId();
341
                // Create personnal folder
342
                if ((int) $has_personal_folder === 1) {
343
                    DB::insert(
344
                        prefixTable('nested_tree'),
345
                        array(
346
                            'parent_id' => '0',
347
                            'title' => $new_user_id,
348
                            'bloquer_creation' => '0',
349
                            'bloquer_modification' => '0',
350
                            'personal_folder' => '1',
351
                            'categories' => '',
352
                        )
353
                    );
354
                    $tree->rebuild();
355
                }
356
                // Create folder and role for domain
357
                if ((int) $new_folder_role_domain === 1) {
358
                    // create folder
359
                    DB::insert(
360
                        prefixTable('nested_tree'),
361
                        array(
362
                            'parent_id' => 0,
363
                            'title' => $domain,
364
                            'personal_folder' => 0,
365
                            'renewal_period' => 0,
366
                            'bloquer_creation' => '0',
367
                            'bloquer_modification' => '0',
368
                        )
369
                    );
370
                    $new_folder_id = DB::insertId();
371
                    // Add complexity
372
                    DB::insert(
373
                        prefixTable('misc'),
374
                        array(
375
                            'type' => 'complex',
376
                            'intitule' => $new_folder_id,
377
                            'valeur' => 50,
378
                            'created_at' => time(),
379
                        )
380
                    );
381
                    // Create role
382
                    DB::insert(
383
                        prefixTable('roles_title'),
384
                        array(
385
                            'title' => $domain,
386
                        )
387
                    );
388
                    $new_role_id = DB::insertId();
389
                    // Associate new role to new folder
390
                    DB::insert(
391
                        prefixTable('roles_values'),
392
                        array(
393
                            'folder_id' => $new_folder_id,
394
                            'role_id' => $new_role_id,
395
                        )
396
                    );
397
                    // Add the new user to this role
398
                    DB::update(
399
                        prefixTable('users'),
400
                        array(
401
                            'fonction_id' => is_int($new_role_id),
402
                        ),
403
                        'id=%i',
404
                        $new_user_id
405
                    );
406
                    // rebuild tree
407
                    $tree->rebuild();
408
                }
409
410
                // Create the API key
411
                DB::insert(
412
                    prefixTable('api'),
413
                    array(
414
                        'type' => 'user',
415
                        'user_id' => $new_user_id,
416
                        'value' => encryptUserObjectKey(base64_encode(base64_encode(uniqidReal(39))), $userKeys['public_key']),
417
                        'timestamp' => time(),
418
                    )
419
                );
420
421
                // get links url
422
                if (empty($SETTINGS['email_server_url']) === true) {
423
                    $SETTINGS['email_server_url'] = $SETTINGS['cpassman_url'];
424
                }
425
426
                // Launch process for user keys creation
427
                // No OTP is provided here, no need.
428
                handleUserKeys(
429
                    (int) $new_user_id,
430
                    (string) $password,
431
                    (int) isset($SETTINGS['maximum_number_of_items_to_treat']) === true ? $SETTINGS['maximum_number_of_items_to_treat'] : NUMBER_ITEMS_IN_BATCH,
432
                    "",
433
                    true,
434
                    true,
435
                    true,
436
                    false,
437
                    (string) $lang->get('email_body_user_config_6'),
438
                );
439
440
                // update LOG
441
                logEvents(
442
                    $SETTINGS,
443
                    'user_mngt',
444
                    'at_user_added',
445
                    (string) $session->get('user-id'),
446
                    $session->get('user-login'),
447
                    (string) $new_user_id
448
                );
449
450
                echo prepareExchangedData(
451
                    array(
452
                        'error' => false,
453
                        'user_id' => $new_user_id,
454
                        'message' => '',
455
                    ),
456
                    'encode'
457
                );
458
            } else {
459
                echo prepareExchangedData(
460
                    array(
461
                        'error' => true,
462
                        'message' => $lang->get('error_user_exists'),
463
                    ),
464
                    'encode'
465
                );
466
            }
467
            break;
468
469
            /*
470
         * Delete the user
471
         */
472
        case 'delete_user':
473
            // Check KEY
474
            if ($post_key !== $session->get('key')) {
475
                echo prepareExchangedData(
476
                    array(
477
                        'error' => true,
478
                        'message' => $lang->get('key_is_not_correct'),
479
                    ),
480
                    'encode'
481
                );
482
                break;
483
            } elseif ($session->get('user-read_only') === 1) {
484
                echo prepareExchangedData(
485
                    array(
486
                        'error' => true,
487
                        'message' => $lang->get('error_not_allowed_to'),
488
                    ),
489
                    'encode'
490
                );
491
                break;
492
            }
493
494
            // Prepare variables
495
            $userId  = filter_var($dataReceived['user_id'], FILTER_SANITIZE_NUMBER_INT);
496
497
            if (empty($userId)) {
498
                echo prepareExchangedData(
499
                    [
500
                        'error' => true,
501
                        'message' => $lang->get('error_empty_data'),
502
                    ],
503
                    'encode'
504
                );
505
                break;
506
            }
507
508
            // Get info about user to delete
509
            $data_user = DB::queryFirstRow(
510
                'SELECT login, admin, isAdministratedByRole FROM ' . prefixTable('users') . '
511
                WHERE id = %i',
512
                $userId 
513
            );        
514
            if (empty($data_user)) {
515
                throw new Exception($lang->get('error_user_not_exists'));
516
            }
517
518
            DB::startTransaction();
519
            try {
520
                // Is this user allowed to do this?
521
                if (
522
                    (int) $session->get('user-admin') === 1
523
                    || (in_array($data_user['isAdministratedByRole'], $session->get('user-roles_array')))
524
                    || ((int) $session->get('user-can_manage_all_users') === 1 && (int) $data_user['admin'] !== 1)
525
                ) {
526
                    $timestamp = time();
527
                    $deletedSuffix = '_deleted_' . $timestamp;
528
529
                    // delete user in database
530
                    DB::update(
531
                        prefixTable('users'),
532
                        array(
533
                            'login' => $data_user['login'].$deletedSuffix,
534
                            'deleted_at' => $timestamp,
535
                            'disabled' => 1,
536
                            'special' => 'none',
537
                            'auth_type' => 'none'
538
                        ),
539
                        'id = %i',
540
                        $userId
541
                    );
542
543
                    /*
544
                    // delete user api
545
                    DB::delete(
546
                        prefixTable('api'),
547
                        'user_id = %i',
548
                        $userId
549
                    );
550
                    
551
                    // Delete cache
552
                    DB::delete(
553
                        prefixTable('cache'),
554
                        'author = %i',
555
                        $userId
556
                    );
557
558
                    // delete personal folder and subfolders
559
                    $data = DB::queryFirstRow(
560
                        'SELECT id FROM ' . prefixTable('nested_tree') . '
561
                        WHERE title = %s AND personal_folder = %i',
562
                        $userId,
563
                        '1'
564
                    );
565
566
                    // Delete tokens
567
                    DB::delete(
568
                        prefixTable('tokens'),
569
                        'user_id = %i',
570
                        $userId
571
                    );
572
573
                    // Delete private keys
574
                    DB::delete(
575
                        prefixTable('user_private_keys'),
576
                        'user_id = %i',
577
                        $userId
578
                    );
579
580
                    // Get through each subfolder
581
                    if (!empty($data['id'])) {
582
                        $folders = $tree->getDescendants($data['id'], true);
583
                        foreach ($folders as $folder) {
584
                            // delete folder
585
                            DB::delete(prefixTable('nested_tree'), 'id = %i AND personal_folder = %i', $folder->id, '1');
586
                            // delete items & logs
587
                            $items = DB::query(
588
                                'SELECT id FROM ' . prefixTable('items') . '
589
                                WHERE id_tree=%i AND perso = %i',
590
                                $folder->id,
591
                                '1'
592
                            );
593
                            foreach ($items as $item) {
594
                                // Delete item
595
                                DB::delete(prefixTable('items'), 'id = %i', $item['id']);
596
                                // log
597
                                DB::delete(prefixTable('log_items'), 'id_item = %i', $item['id']);
598
                            }
599
                        }
600
                        // rebuild tree
601
                        $tree = new NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
602
                        $tree->rebuild();
603
                    }
604
605
                    // Delete objects keys
606
                    deleteUserObjetsKeys((int) $userId, $SETTINGS);
607
608
609
                    // Delete any process related to user
610
                    $processes = DB::query(
611
                        'SELECT increment_id
612
                        FROM ' . prefixTable('background_tasks') . '
613
                        WHERE JSON_EXTRACT(arguments, "$.new_user_id") = %i',
614
                        $userId
615
                    );
616
                    $process_id = -1;
617
                    foreach ($processes as $process) {
618
                        // Delete task
619
                        DB::delete(
620
                            prefixTable('background_subtasks'),
621
                            'task_id = %i',
622
                            $process['increment_id']
623
                        );
624
                        $process_id = $process['increment_id'];
625
                    }
626
                    // Delete main process
627
                    if ($process_id > -1) {
628
                        DB::delete(
629
                            prefixTable('background_tasks'),
630
                            'increment_id = %i',
631
                            $process_id
632
                        );
633
                    }
634
                    */
635
                    
636
                    // update LOG
637
                    logEvents($SETTINGS, 'user_mngt', 'at_user_deleted', (string) $session->get('user-id'), $session->get('user-login'), $userId);
638
639
                    DB::commit();
640
641
                    //Send back
642
                    echo prepareExchangedData(
643
                        array(
644
                            'error' => false,
645
                            'message' => '',
646
                        ),
647
                        'encode'
648
                    );
649
                } else {
650
                    //Send back
651
                    echo prepareExchangedData(
652
                        array(
653
                            'error' => false,
654
                            'message' => $lang->get('error_not_allowed_to'),
655
                        ),
656
                        'encode'
657
                    );
658
                }
659
            } catch (Exception $e) {
660
                DB::rollback();
661
                
662
                echo prepareExchangedData(
663
                    [
664
                        'error' => true,
665
                        'message' => $lang->get('error') . ': ' . $e->getMessage(),
666
                    ],
667
                    'encode'
668
                );
669
            }
670
            break;
671
672
        /*
673
         * Check the domain
674
         */
675
        case 'check_domain':
676
            $return = array();
677
            // Check if folder exists
678
            $data = DB::query(
679
                'SELECT * FROM ' . prefixTable('nested_tree') . '
680
                WHERE title = %s AND parent_id = %i',
681
                filter_input(INPUT_POST, 'domain', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
682
                '0'
683
            );
684
            $counter = DB::count();
685
            if ($counter != 0) {
686
                $return['folder'] = 'exists';
687
            } else {
688
                $return['folder'] = 'not_exists';
689
            }
690
            // Check if role exists
691
            $data = DB::query(
692
                'SELECT * FROM ' . prefixTable('roles_title') . '
693
                WHERE title = %s',
694
                filter_input(INPUT_POST, 'domain', FILTER_SANITIZE_FULL_SPECIAL_CHARS)
695
            );
696
            $counter = DB::count();
697
            if ($counter != 0) {
698
                $return['role'] = 'exists';
699
            } else {
700
                $return['role'] = 'not_exists';
701
            }
702
703
            echo json_encode($return);
704
            break;
705
706
        /*
707
         * delete the timestamp value for specified user => disconnect
708
         */
709
        case 'disconnect_user':
710
            // Check KEY
711
            if (filter_input(INPUT_POST, 'key', FILTER_SANITIZE_FULL_SPECIAL_CHARS) !== filter_var($session->get('key'), FILTER_SANITIZE_FULL_SPECIAL_CHARS)) {
712
                echo '[ { "error" : "key_not_conform" } ]';
713
                break;
714
            }
715
716
            $post_user_id = filter_input(INPUT_POST, 'user_id', FILTER_SANITIZE_NUMBER_INT);
717
718
            // Get info about user to delete
719
            $data_user = DB::queryFirstRow(
720
                'SELECT admin, isAdministratedByRole, gestionnaire
721
                FROM ' . prefixTable('users') . '
722
                WHERE id = %i',
723
                $post_user_id
724
            );
725
726
            // Is this user allowed to do this?
727
            if (
728
                (int) $session->get('user-admin') === 1
729
                || (in_array($data_user['isAdministratedByRole'], $session->get('user-roles_array')))
730
                || ((int) $session->get('user-can_manage_all_users') === 1 && (int) $data_user['admin'] !== 1)
731
            ) {
732
                // Do
733
                DB::update(
734
                    prefixTable('users'),
735
                    array(
736
                        'timestamp' => '',
737
                        'key_tempo' => '',
738
                        'session_end' => '',
739
                    ),
740
                    'id = %i',
741
                    $post_user_id
742
                );
743
            }
744
            break;
745
746
        /*
747
         * Get user info
748
         */
749
        case 'get_user_info':
750
            // Check KEY
751
            if ($post_key !== $session->get('key')) {
752
                echo prepareExchangedData(
753
                    array(
754
                        'error' => true,
755
                        'message' => $lang->get('key_is_not_correct'),
756
                    ),
757
                    'encode'
758
                );
759
                break;
760
            } elseif ($session->get('user-read_only') === 1) {
761
                echo prepareExchangedData(
762
                    array(
763
                        'error' => true,
764
                        'message' => $lang->get('error_not_allowed_to'),
765
                    ),
766
                    'encode'
767
                );
768
                break;
769
            }
770
            
771
            // Prepare variables
772
            $post_id = filter_var($dataReceived['user_id'], FILTER_SANITIZE_NUMBER_INT);
773
774
            // Get info about user
775
            $rowUser = DB::queryFirstRow(
776
                'SELECT *
777
                FROM ' . prefixTable('users') . '
778
                WHERE id = %i',
779
                $post_id
780
            );
781
782
            // Is this user allowed to do this?
783
            if (
784
                (int) $session->get('user-admin') === 1
785
                || (in_array($rowUser['isAdministratedByRole'], $session->get('user-roles_array')) === true)
786
                || ((int) $session->get('user-can_manage_all_users') === 1 && $rowUser['admin'] !== '1')
787
            ) {
788
                $arrData = array();
789
                $arrFunction = array();
790
                $arrMngBy = array();
791
                $arrFldForbidden = array();
792
                $arrFldAllowed = array();
793
794
                //Build tree
795
                $tree = new NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
796
797
                // get FUNCTIONS
798
                $functionsList = array();
799
                $selected = '';
800
                $users_functions = array_filter(array_unique(explode(';', empty($rowUser['fonction_id'].';'.$rowUser['roles_from_ad_groups']) === true ? '' : $rowUser['fonction_id'].';'.$rowUser['roles_from_ad_groups'])));
801
802
                $session->set('user-roles_array', explode(';', $session->get('user-roles')));
803
                $rows = DB::query('
804
                    SELECT id,title,creator_id 
805
                    FROM ' . prefixTable('roles_title') .'
806
                    WHERE id IN %li',
807
                    $session->get('user-roles_array')
808
                );
809
                foreach ($rows as $record) {
810
                    if (
811
                        (int) $session->get('user-admin') === 1
812
                        || (((int) $session->get('user-manager') === 1 || (int) $session->get('user-can_manage_all_users') === 1))
813
                    ) {
814
                        if (in_array($record['id'], $users_functions)) {
815
                            $selected = 'selected';
816
817
                            array_push(
818
                                $arrFunction,
819
                                array(
820
                                    'title' => $record['title'],
821
                                    'id' => $record['id'],
822
                                )
823
                            );
824
                        } else {
825
                            $selected = '';
826
                        }
827
828
                        array_push(
829
                            $functionsList,
830
                            array(
831
                                'title' => $record['title'],
832
                                'id' => $record['id'],
833
                                'selected' => $selected,
834
                            )
835
                        );
836
                    }
837
                }
838
839
                // get MANAGEDBY
840
                $rolesList = array();
841
                $managedBy = array();
842
                $selected = '';
843
                $rows = DB::query('SELECT id,title FROM ' . prefixTable('roles_title') . ' ORDER BY title ASC');
844
                foreach ($rows as $reccord) {
845
                    $rolesList[$reccord['id']] = array('id' => $reccord['id'], 'title' => $reccord['title']);
846
                }
847
848
                array_push(
849
                    $managedBy,
850
                    array(
851
                        'title' => $lang->get('administrators_only'),
852
                        'id' => 0,
853
                    )
854
                );
855
                foreach ($rolesList as $fonction) {
856
                    if ($session->get('user-admin') === 1 || in_array($fonction['id'], $session->get('user-roles_array'))) {
857
                        if ($rowUser['isAdministratedByRole'] == $fonction['id']) {
858
                            $selected = 'selected';
859
860
                            array_push(
861
                                $arrMngBy,
862
                                array(
863
                                    'title' => $fonction['title'],
864
                                    'id' => $fonction['id'],
865
                                )
866
                            );
867
                        } else {
868
                            $selected = '';
869
                        }
870
871
                        array_push(
872
                            $managedBy,
873
                            array(
874
                                'title' => $lang->get('managers_of') . ' ' . $fonction['title'],
875
                                'id' => $fonction['id'],
876
                                'selected' => $selected,
877
                            )
878
                        );
879
                    }
880
                }
881
882
                if (count($arrMngBy) === 0) {
883
                    array_push(
884
                        $arrMngBy,
885
                        array(
886
                            'title' => $lang->get('administrators_only'),
887
                            'id' => '0',
888
                        )
889
                    );
890
                }
891
892
                // get FOLDERS FORBIDDEN
893
                $forbiddenFolders = array();
894
                $userForbidFolders = explode(';', is_null($rowUser['groupes_interdits']) === true ? '' : $rowUser['groupes_interdits']);
895
                $tree_desc = $tree->getDescendants();
896
                foreach ($tree_desc as $t) {
897
                    if (in_array($t->id, $session->get('user-accessible_folders')) && in_array($t->id, $session->get('user-personal_visible_folders')) === false) {
898
                        $selected = '';
899
                        if (in_array($t->id, $userForbidFolders)) {
900
                            $selected = 'selected';
901
902
                            array_push(
903
                                $arrFldForbidden,
904
                                array(
905
                                    'title' => htmlspecialchars($t->title, ENT_COMPAT, 'UTF-8'),
906
                                    'id' => $t->id,
907
                                )
908
                            );
909
                        }
910
                        array_push(
911
                            $forbiddenFolders,
912
                            array(
913
                                'id' => $t->id,
914
                                'selected' => $selected,
915
                                'title' => @htmlspecialchars($t->title, ENT_COMPAT, 'UTF-8'),
916
                            )
917
                        );
918
                    }
919
                }
920
921
                // get FOLDERS ALLOWED
922
                $allowedFolders = array();
923
                $userAllowFolders = explode(';', $rowUser['groupes_visibles']);
924
                $tree_desc = $tree->getDescendants();
925
                foreach ($tree_desc as $t) {
926
                    if (
927
                        in_array($t->id, $session->get('user-accessible_folders')) === true
928
                        && in_array($t->id, $session->get('user-personal_visible_folders')) === false
929
                    ) {
930
                        $selected = '';
931
                        if (in_array($t->id, $userAllowFolders)) {
932
                            $selected = 'selected';
933
934
                            array_push(
935
                                $arrFldAllowed,
936
                                array(
937
                                    'title' => htmlspecialchars($t->title, ENT_COMPAT, 'UTF-8'),
938
                                    'id' => $t->id,
939
                                )
940
                            );
941
                        }
942
943
                        array_push(
944
                            $allowedFolders,
945
                            array(
946
                                'id' => $t->id,
947
                                'selected' => $selected,
948
                                'title' => @htmlspecialchars($t->title, ENT_COMPAT, 'UTF-8'),
949
                            )
950
                        );
951
                    }
952
                }
953
954
                // get USER STATUS
955
                if ($rowUser['disabled'] == 1) {
956
                    $arrData['info'] = $lang->get('user_info_locked') . '<br><input type="checkbox" value="unlock" name="1" class="chk">&nbsp;<label for="1">' . $lang->get('user_info_unlock_question') . '</label><br><input type="checkbox"  value="delete" id="account_delete" class="chk mr-2" name="2" onclick="confirmDeletion()">label for="2">' . $lang->get('user_info_delete_question') . '</label>';
957
                } else {
958
                    $arrData['info'] = $lang->get('user_info_active') . '<br><input type="checkbox" value="lock" class="chk">&nbsp;' . $lang->get('user_info_lock_question');
959
                }
960
961
                $arrData['error'] = false;
962
                $arrData['login'] = $rowUser['login'];
963
                $arrData['name'] = empty($rowUser['name']) === false && $rowUser['name'] !== NULL ? $rowUser['name'] : '';
964
                $arrData['lastname'] = empty($rowUser['lastname']) === false && $rowUser['lastname'] !== NULL ? $rowUser['lastname'] : '';
965
                $arrData['email'] = $rowUser['email'];
966
                $arrData['function'] = $functionsList;
967
                $arrData['managedby'] = $managedBy;
968
                $arrData['foldersForbid'] = $forbiddenFolders;
969
                $arrData['foldersAllow'] = $allowedFolders;
970
                $arrData['share_function'] = $arrFunction;
971
                $arrData['share_managedby'] = $arrMngBy;
972
                $arrData['share_forbidden'] = $arrFldForbidden;
973
                $arrData['share_allowed'] = $arrFldAllowed;
974
                $arrData['disabled'] = (int) $rowUser['disabled'];
975
                $arrData['gestionnaire'] = (int) $rowUser['gestionnaire'];
976
                $arrData['read_only'] = (int) $rowUser['read_only'];
977
                $arrData['can_create_root_folder'] = (int) $rowUser['can_create_root_folder'];
978
                $arrData['personal_folder'] = (int) $rowUser['personal_folder'];
979
                $arrData['can_manage_all_users'] = (int) $rowUser['can_manage_all_users'];
980
                $arrData['admin'] = (int) $rowUser['admin'];
981
                $arrData['password'] = $password_do_not_change;
982
                $arrData['mfa_enabled'] = (int) $rowUser['mfa_enabled'];
983
984
                echo prepareExchangedData(
985
                    $arrData,
986
                    'encode'
987
                );
988
            } else {
989
                echo prepareExchangedData(
990
                    array(
991
                        'error' => true,
992
                        'message' => $lang->get('error_not_allowed_to'),
993
                    ),
994
                    'encode'
995
                );
996
            }
997
998
            break;
999
1000
        /*
1001
         * EDIT user
1002
         */
1003
        case 'store_user_changes':
1004
            // Check KEY
1005
            if ($post_key !== $session->get('key')) {
1006
                echo prepareExchangedData(
1007
                    array(
1008
                        'error' => true,
1009
                        'message' => $lang->get('key_is_not_correct'),
1010
                    ),
1011
                    'encode'
1012
                );
1013
                break;
1014
            } elseif ($session->get('user-read_only') === 1) {
1015
                echo prepareExchangedData(
1016
                    array(
1017
                        'error' => true,
1018
                        'message' => $lang->get('error_not_allowed_to'),
1019
                    ),
1020
                    'encode'
1021
                );
1022
                break;
1023
            }
1024
1025
            // Prepare variables
1026
            $post_id = filter_var($dataReceived['user_id'], FILTER_SANITIZE_NUMBER_INT);
1027
            $post_login = filter_var($dataReceived['login'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
1028
            $post_email = filter_var($dataReceived['email'], FILTER_SANITIZE_EMAIL);
1029
            $post_lastname = filter_var($dataReceived['lastname'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
1030
            $post_name = filter_var($dataReceived['name'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
1031
            $post_is_admin = filter_var($dataReceived['admin'], FILTER_SANITIZE_NUMBER_INT);
1032
            $post_is_manager = filter_var($dataReceived['manager'], FILTER_SANITIZE_NUMBER_INT);
1033
            $post_is_hr = filter_var($dataReceived['hr'], FILTER_SANITIZE_NUMBER_INT);
1034
            $post_is_read_only = filter_var($dataReceived['read_only'], FILTER_SANITIZE_NUMBER_INT);
1035
            $post_has_personal_folder = filter_var($dataReceived['personal_folder'], FILTER_SANITIZE_NUMBER_INT);
1036
            $post_is_administrated_by = filter_var($dataReceived['isAdministratedByRole'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
1037
            $post_groups = filter_var_array($dataReceived['groups'], FILTER_SANITIZE_NUMBER_INT);
1038
            $post_allowed_flds = filter_var_array($dataReceived['allowed_flds'], FILTER_SANITIZE_NUMBER_INT);
1039
            $post_forbidden_flds = filter_var_array($dataReceived['forbidden_flds'], FILTER_SANITIZE_NUMBER_INT);
1040
            $post_root_level = filter_var($dataReceived['form-create-root-folder'], FILTER_SANITIZE_NUMBER_INT);
1041
            $post_mfa_enabled = filter_var($dataReceived['mfa_enabled'], FILTER_SANITIZE_NUMBER_INT);
1042
1043
            // Get info about user to modify
1044
            $data_user = DB::queryFirstRow(
1045
                'SELECT admin, gestionnaire, can_manage_all_users, isAdministratedByRole FROM ' . prefixTable('users') . '
1046
                WHERE id = %i',
1047
                $post_id
1048
            );
1049
1050
            // If user removes administrator role on administrator user
1051
            // then ensure that it exists still one administrator
1052
            if ((int) $data_user['admin'] === 1 && (int) $post_is_admin !== 1) {
1053
                // count number of admins
1054
                $users = DB::query(
1055
                    'SELECT id
1056
                    FROM ' . prefixTable('users') . '
1057
                    WHERE admin = 1 AND email != "" AND pw != "" AND id != %i',
1058
                    $post_id
1059
                );
1060
                if (DB::count() === 0) {
1061
                    echo prepareExchangedData(
1062
                        array(
1063
                            'error' => true,
1064
                            'message' => $lang->get('at_least_one_administrator_is_requested'),
1065
                        ),
1066
                        'encode'
1067
                    );
1068
                    break;
1069
                }
1070
            }
1071
            
1072
            // Init post variables
1073
            $post_action_to_perform = filter_var(htmlspecialchars_decode($dataReceived['action_on_user']), FILTER_SANITIZE_FULL_SPECIAL_CHARS);
1074
            $action_to_perform_after = '';
1075
            
1076
            // Exclude roles from AD - PR #3635
1077
            $adRoles = DB::query(
1078
                'SELECT roles_from_ad_groups
1079
                FROM ' . prefixTable('users') . '
1080
                WHERE id = %i',
1081
                $post_id
1082
            )[0]['roles_from_ad_groups'];
1083
            $fonctions = [];
1084
            if (!is_null($post_groups) && !empty($adRoles)) {
1085
                foreach ($post_groups as $post_group) {
1086
                    if (!in_array($post_group, explode(';', $adRoles))) {
1087
                        $fonctions[] = $post_group;
1088
                    }
1089
                }
1090
            }
1091
            $post_groups = empty($fonctions) === true ? $post_groups : $fonctions;
1092
1093
            // Build array of update
1094
            $changeArray = array(
1095
                'login' => $post_login,
1096
                'name' => $post_name,
1097
                'lastname' => $post_lastname,
1098
                'email' => $post_email,
1099
                'admin' => empty($post_is_admin) === true ? 0 : $post_is_admin,
1100
                'can_manage_all_users' => empty($post_is_hr) === true ? 0 : $post_is_hr,
1101
                'gestionnaire' => empty($post_is_manager) === true ? 0 : $post_is_manager,
1102
                'read_only' => empty($post_is_read_only) === true ? 0 : $post_is_read_only,
1103
                'personal_folder' => empty($post_has_personal_folder) === true ? 0 : $post_has_personal_folder,
1104
                'user_language' => $SETTINGS['default_language'],
1105
                'fonction_id' => is_null($post_groups) === true ? '' : implode(';', array_unique($post_groups)),
1106
                'groupes_interdits' => is_null($post_forbidden_flds) === true ? '' : implode(';', array_unique($post_forbidden_flds)),
1107
                'groupes_visibles' => is_null($post_allowed_flds) === true ? '' : implode(';', array_unique($post_allowed_flds)),
1108
                'isAdministratedByRole' => $post_is_administrated_by,
1109
                'can_create_root_folder' => empty($post_root_level) === true ? 0 : $post_root_level,
1110
                'mfa_enabled' => empty($post_mfa_enabled) === true ? 0 : $post_mfa_enabled,
1111
            );
1112
1113
            // Manage user password change
1114
            // This can occur only if user changes his own password
1115
            // In other case, next condition must be wrong
1116
            if (
1117
                isset($post_password) === true
1118
                && $post_password !== $password_do_not_change
1119
                && $post_id === $session->get('user-id')
1120
            ) {
1121
                // load password library
1122
                $passwordManager = new PasswordManager();
1123
1124
                $changeArray['pw'] = $passwordManager->hashPassword($post_password);
1125
                $changeArray['key_tempo'] = '';
1126
1127
                // We need to adapt the private key with new password
1128
                $session->set('user-private_key', encryptPrivateKey($post_password, $session->get('user-private_key')));
1129
            }
1130
1131
            // Empty user
1132
            if (empty($post_login) === true) {
1133
                echo prepareExchangedData(
1134
                    array(
1135
                        'error' => true,
1136
                        'message' => $lang->get('error_empty_data'),
1137
                    ),
1138
                    'encode'
1139
                );
1140
                break;
1141
            }
1142
1143
            // User has email?
1144
            if (empty($post_email) === true) {
1145
                echo prepareExchangedData(
1146
                    array(
1147
                        'error' => true,
1148
                        'message' => $lang->get('error_no_email'),
1149
                    ),
1150
                    'encode'
1151
                );
1152
                break;
1153
            }
1154
1155
            // Is this user allowed to do this?
1156
            if (
1157
                // Administrator user
1158
                (int) $session->get('user-admin') === 1
1159
                // Manager of basic/ro users in this role but don't allow promote user to admin or managers roles
1160
                || ((int) $session->get('user-manager') === 1
1161
                    && in_array($data_user['isAdministratedByRole'], $session->get('user-roles_array'))
1162
                    && (int) $post_is_admin !== 1 && (int) $data_user['admin'] !== 1
1163
                    && (int) $post_is_hr !== 1 && (int) $data_user['can_manage_all_users'] !== 1
1164
                    && (int) $post_is_manager !== 1 && (int) $data_user['gestionnaire'] !== 1)
1165
                // Manager of all basic/ro users but don't allow promote user to admin or managers roles
1166
                || ((int) $session->get('user-can_manage_all_users') === 1
1167
                    && (int) $post_is_admin !== 1 && (int) $data_user['admin'] !== 1
1168
                    && (int) $post_is_hr !== 1 && (int) $data_user['can_manage_all_users'] !== 1
1169
                    && (int) $post_is_manager !== 1 && (int) $data_user['gestionnaire'] !== 1)
1170
            ) {
1171
                // delete account
1172
                // delete user in database
1173
                if ($post_action_to_perform === 'delete') {
1174
                    DB::delete(
1175
                        prefixTable('users'),
1176
                        'id = %i',
1177
                        $post_id
1178
                    );
1179
                    // delete personal folder and subfolders
1180
                    $data = DB::queryFirstRow(
1181
                        'SELECT id FROM ' . prefixTable('nested_tree') . '
1182
                        WHERE title = %s AND personal_folder = %i',
1183
                        $post_id,
1184
                        '1'
1185
                    );
1186
                    // Get through each subfolder
1187
                    if (!empty($data['id'])) {
1188
                        $folders = $tree->getDescendants($data['id'], true);
1189
                        foreach ($folders as $folder) {
1190
                            // delete folder
1191
                            DB::delete(prefixTable('nested_tree'), 'id = %i AND personal_folder = %i', $folder->id, '1');
1192
                            // delete items & logs
1193
                            $items = DB::query(
1194
                                'SELECT id FROM ' . prefixTable('items') . '
1195
                                WHERE id_tree=%i AND perso = %i',
1196
                                $folder->id,
1197
                                '1'
1198
                            );
1199
                            foreach ($items as $item) {
1200
                                // Delete item
1201
                                DB::delete(prefixTable('items'), 'id = %i', $item['id']);
1202
                                // log
1203
                                DB::delete(prefixTable('log_items'), 'id_item = %i', $item['id']);
1204
                            }
1205
                        }
1206
                        // rebuild tree
1207
                        $tree = new NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
1208
                        $tree->rebuild();
1209
                    }
1210
                    // update LOG
1211
                    logEvents($SETTINGS, 'user_mngt', 'at_user_deleted', (string) $session->get('user-id'), $session->get('user-login'), $post_id);
1212
                } else {
1213
                    // Get old data about user
1214
                    $oldData = DB::queryFirstRow(
1215
                        'SELECT * FROM ' . prefixTable('users') . '
1216
                        WHERE id = %i',
1217
                        $post_id
1218
                    );
1219
1220
                    // update SESSION
1221
                    if ($session->get('user-id') === $post_id) {
1222
                        $session->set('user-lastname', $post_lastname);
1223
                        $session->set('user-name', $post_name);
1224
                        $session->set('user-email', $post_email);
1225
                    }
1226
1227
                    // Has the groups changed? If yes then ask for a keys regeneration
1228
                    $arrOldData = array_filter(explode(';', $oldData['fonction_id']));
1229
                    $post_groups = is_null($post_groups) === true ? array() : array_filter($post_groups);
1230
1231
                    if ($arrOldData != $post_groups && (int) $oldData['admin'] !== 1) {
1232
                        $action_to_perform_after = 'encrypt_keys';
1233
                    }
1234
1235
                    // update user
1236
                    DB::update(
1237
                        prefixTable('users'),
1238
                        $changeArray,
1239
                        'id = %i',
1240
                        $post_id
1241
                    );
1242
1243
                    // CLear cache tree for this user to force tree
1244
                    DB::delete(
1245
                        prefixTable('cache_tree'),
1246
                        'user_id = %i',
1247
                        $post_id
1248
                    );
1249
1250
                    // update LOG
1251
                    if ($oldData['email'] !== $post_email) {
1252
                        logEvents($SETTINGS, 'user_mngt', 'at_user_email_changed:' . $oldData['email'], (string) $session->get('user-id'), $session->get('user-login'), $post_id);
1253
                    }
1254
                }
1255
                echo prepareExchangedData(
1256
                    array(
1257
                        'error' => false,
1258
                        'message' => '',
1259
                        'post_action' => $action_to_perform_after,
1260
                    ),
1261
                    'encode'
1262
                );
1263
            } else {
1264
                echo prepareExchangedData(
1265
                    array(
1266
                        'error' => true,
1267
                        'message' => $lang->get('error_not_allowed_to'),
1268
                    ),
1269
                    'encode'
1270
                );
1271
            }
1272
            break;
1273
1274
        /*
1275
         * IS LOGIN AVAILABLE?
1276
         */
1277
        case 'is_login_available':
1278
            // Check KEY
1279
            if ($post_key !== $session->get('key')) {
1280
                echo prepareExchangedData(
1281
                    array(
1282
                        'error' => true,
1283
                        'message' => $lang->get('key_is_not_correct'),
1284
                    ),
1285
                    'encode'
1286
                );
1287
                break;
1288
            } elseif ($session->get('user-read_only') === 1) {
1289
                echo prepareExchangedData(
1290
                    array(
1291
                        'error' => true,
1292
                        'message' => $lang->get('error_not_allowed_to'),
1293
                    ),
1294
                    'encode'
1295
                );
1296
                break;
1297
            }
1298
1299
            DB::queryFirstRow(
1300
                'SELECT * FROM ' . prefixTable('users') . '
1301
                WHERE login = %s
1302
                AND deleted_at IS NULL',
1303
                filter_input(INPUT_POST, 'login', FILTER_SANITIZE_FULL_SPECIAL_CHARS)
1304
            );
1305
1306
            echo prepareExchangedData(
1307
                array(
1308
                    'error' => false,
1309
                    'login_exists' => DB::count(),
1310
                ),
1311
                'encode'
1312
            );
1313
1314
            break;
1315
1316
        /*
1317
         * GET USER FOLDER RIGHT
1318
         */
1319
        case 'user_folders_rights':
1320
            // Check KEY
1321
            if ($post_key !== $session->get('key')) {
1322
                echo prepareExchangedData(
1323
                    array(
1324
                        'error' => true,
1325
                        'message' => $lang->get('key_is_not_correct'),
1326
                    ),
1327
                    'encode'
1328
                );
1329
                break;
1330
            } elseif ($session->get('user-read_only') === 1) {
1331
                echo prepareExchangedData(
1332
                    array(
1333
                        'error' => true,
1334
                        'message' => $lang->get('error_not_allowed_to'),
1335
                    ),
1336
                    'encode'
1337
                );
1338
                break;
1339
            }
1340
1341
            // Prepare variables
1342
            $post_id = filter_input(INPUT_POST, 'user_id', FILTER_SANITIZE_NUMBER_INT);
1343
1344
            $arrData = array();
1345
1346
            //Build tree
1347
            $tree = new NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
1348
1349
            // get User info
1350
            $rowUser = DB::queryFirstRow(
1351
                'SELECT login, name, lastname, email, disabled, fonction_id, groupes_interdits, groupes_visibles, isAdministratedByRole, avatar_thumb, roles_from_ad_groups
1352
                FROM ' . prefixTable('users') . '
1353
                WHERE id = %i',
1354
                $post_id
1355
            );
1356
1357
            // get rights
1358
            $arrFolders = [];
1359
            $html = '';
1360
1361
            if (isset($SETTINGS['ldap_mode']) === true && (int) $SETTINGS['ldap_mode'] === 1 && isset($SETTINGS['enable_ad_users_with_ad_groups']) === true && (int) $SETTINGS['enable_ad_users_with_ad_groups'] === 1) {
1362
                $rowUser['fonction_id'] = empty($rowUser['fonction_id'])  === true ? $rowUser['roles_from_ad_groups'] : $rowUser['fonction_id']. ';' . $rowUser['roles_from_ad_groups'];
1363
            }
1364
            $arrData['functions'] = array_filter(explode(';', $rowUser['fonction_id']));
1365
            $arrData['allowed_folders'] = array_filter(explode(';', $rowUser['groupes_visibles']));
1366
            $arrData['denied_folders'] = array_filter(explode(';', $rowUser['groupes_interdits']));
1367
1368
            // Exit if no roles
1369
            if (count($arrData['functions']) > 0) {
1370
                // refine folders based upon roles
1371
                $rows = DB::query(
1372
                    'SELECT rv.folder_id, rv.type
1373
                    FROM ' . prefixTable('roles_values') . ' as rv
1374
                    INNER JOIN ' . prefixTable('nested_tree') . ' as nt ON rv.folder_id = nt.id
1375
                    WHERE rv.role_id IN %ls AND nt.personal_folder = 0
1376
                    ORDER BY rv.folder_id ASC',
1377
                    $arrData['functions']
1378
                );
1379
                foreach ($rows as $record) {
1380
                    $bFound = false;
1381
                    $x = 0;
1382
                    foreach ($arrFolders as $fld) {
1383
                        if ($fld['id'] === $record['folder_id']) {
1384
                            // get the level of access on the folder
1385
                            $arrFolders[$x]['type'] = evaluateFolderAccesLevel($record['type'], $arrFolders[$x]['type']);
1386
                            $bFound = true;
1387
                            break;
1388
                        }
1389
                        ++$x;
1390
                    }
1391
                    if ($bFound === false && in_array($record['folder_id'], $arrData['denied_folders']) === false) {
1392
                        array_push($arrFolders, array('id' => $record['folder_id'], 'type' => $record['type'], 'special' => false));
1393
                    }
1394
                }
1395
1396
                // add allowed folders
1397
                foreach($arrData['allowed_folders'] as $Fld) {
1398
                    array_push($arrFolders, array('id' => $Fld, 'type' => 'W', 'special' => true));
1399
                }
1400
                
1401
                $tree_desc = $tree->getDescendants();
1402
                foreach ($tree_desc as $t) {
1403
                    foreach ($arrFolders as $fld) {
1404
                        if ($fld['id'] === $t->id) {
1405
                            // get folder name
1406
                            $row = DB::queryFirstRow(
1407
                                'SELECT title, nlevel, id
1408
                                FROM ' . prefixTable('nested_tree') . '
1409
                                WHERE id = %i',
1410
                                $fld['id']
1411
                            );
1412
1413
                            // manage indentation
1414
                            $ident = '';
1415
                            for ($y = 1; $y < $row['nlevel']; ++$y) {
1416
                                $ident .= '<i class="fas fa-long-arrow-alt-right mr-2"></i>';
1417
                            }
1418
1419
                            // manage right icon
1420
                            if ($fld['type'] == 'W') {
1421
                                $label = '<i class="fas fa-indent infotip text-success mr-2" title="' . $lang->get('write') . '"></i>' .
1422
                                    '<i class="fas fa-edit infotip text-success mr-2" title="' . $lang->get('edit') . '"></i>' .
1423
                                    '<i class="fas fa-eraser infotip text-success" title="' . $lang->get('delete') . '"></i>';
1424
                            } elseif ($fld['type'] == 'ND') {
1425
                                $label = '<i class="fas fa-indent infotip text-warning mr-2" title="' . $lang->get('write') . '"></i>' .
1426
                                    '<i class="fas fa-edit infotip text-success mr-2" title="' . $lang->get('edit') . '"></i>' .
1427
                                    '<i class="fas fa-eraser infotip text-danger" title="' . $lang->get('no_delete') . '"></i>';
1428
                            } elseif ($fld['type'] == 'NE') {
1429
                                $label = '<i class="fas fa-indent infotip text-warning mr-2" title="' . $lang->get('write') . '"></i>' .
1430
                                    '<i class="fas fa-edit infotip text-danger mr-2" title="' . $lang->get('no_edit') . '"></i>' .
1431
                                    '<i class="fas fa-eraser infotip text-success" title="' . $lang->get('delete') . '"></i>';
1432
                            } elseif ($fld['type'] == 'NDNE') {
1433
                                $label = '<i class="fas fa-indent infotip text-warning mr-2" title="' . $lang->get('write') . '"></i>' .
1434
                                    '<i class="fas fa-edit infotip text-danger mr-2" title="' . $lang->get('no_edit') . '"></i>' .
1435
                                    '<i class="fas fa-eraser infotip text-danger" title="' . $lang->get('no_delete') . '"></i>';
1436
                            } elseif ($fld['type'] == '') {
1437
                                $label = '<i class="fas fa-eye-slash infotip text-danger mr-2" title="' . $lang->get('no_access') . '"></i>';
1438
                            } else {
1439
                                $label = '<i class="fas fa-eye infotip text-info mr-2" title="' . $lang->get('read') . '"></i>';
1440
                            }
1441
1442
                            $html .= '<tr><td>' . $ident . $row['title'] .
1443
                                ' <small class="text-info">[' . $row['id'] . ']</small>'.
1444
                                ($fld['special'] === true ? '<i class="fas fa-user-tag infotip text-primary ml-5" title="' . $lang->get('user_specific_right') . '"></i>' : '').
1445
                                '</td><td>' . $label . '</td></tr>';
1446
                            break;
1447
                        }
1448
                    }
1449
                }
1450
1451
                $html_full = '<table id="table-folders" class="table table-bordered table-striped dt-responsive nowrap" style="width:100%"><tbody>' .
1452
                    $html . '</tbody></table>';
1453
            } else {
1454
                $html_full = '';
1455
            }
1456
1457
            echo prepareExchangedData(
1458
                array(
1459
                    'html' => $html_full,
1460
                    'error' => false,
1461
                    'login' => $rowUser['login'],
1462
                    'message' => '',
1463
                ),
1464
                'encode'
1465
            );
1466
            break;
1467
1468
        /*
1469
         * GET LIST OF USERS
1470
         */
1471
        case 'get_list_of_users_for_sharing':
1472
            // Check KEY
1473
            if ($post_key !== $session->get('key')) {
1474
                echo prepareExchangedData(
1475
                    array(
1476
                        'error' => true,
1477
                        'message' => $lang->get('key_is_not_correct'),
1478
                    ),
1479
                    'encode'
1480
                );
1481
                break;
1482
            } elseif ($session->get('user-read_only') === 1) {
1483
                echo prepareExchangedData(
1484
                    array(
1485
                        'error' => true,
1486
                        'message' => $lang->get('error_not_allowed_to'),
1487
                    ),
1488
                    'encode'
1489
                );
1490
                break;
1491
            }
1492
1493
            $arrUsers = [];
1494
1495
            if ((int) $session->get('user-admin') === 0 && (int) $session->get('user-can_manage_all_users') === 0) {
1496
                $rows = DB::query(
1497
                    'SELECT *
1498
                    FROM ' . prefixTable('users') . '
1499
                    WHERE admin = %i AND isAdministratedByRole IN %ls',
1500
                    '0',
1501
                    array_filter($session->get('user-roles_array'))
1502
                );
1503
            } else {
1504
                $rows = DB::query(
1505
                    'SELECT *
1506
                    FROM ' . prefixTable('users') . '
1507
                    WHERE admin = %i',
1508
                    '0'
1509
                );
1510
            }
1511
1512
            foreach ($rows as $record) {
1513
                // Get roles
1514
                $groups = [];
1515
                $groupIds = [];
1516
                foreach (explode(';', $record['fonction_id']) as $group) {
1517
                    $tmp = DB::queryFirstRow(
1518
                        'SELECT id, title FROM ' . prefixTable('roles_title') . '
1519
                        WHERE id = %i',
1520
                        $group
1521
                    );
1522
                    if ($tmp !== null) {
1523
                        array_push($groups, $tmp['title']);
1524
                        array_push($groupIds, $tmp['id']);
1525
                    }
1526
                }
1527
1528
                // Get managed_by
1529
                $managedBy = DB::queryFirstRow(
1530
                    'SELECT id, title FROM ' . prefixTable('roles_title') . '
1531
                    WHERE id = %i',
1532
                    $record['isAdministratedByRole']
1533
                );
1534
1535
                // Get Allowed folders
1536
                $foldersAllowed = [];
1537
                $foldersAllowedIds = [];
1538
                foreach (explode(';', $record['groupes_visibles']) as $role) {
1539
                    $tmp = DB::queryFirstRow(
1540
                        'SELECT id, title FROM ' . prefixTable('nested_tree') . '
1541
                        WHERE id = %i',
1542
                        $role
1543
                    );
1544
                    array_push($foldersAllowed, $tmp !== null ? $tmp['title'] : $lang->get('none'));
1545
                    array_push($foldersAllowedIds, $tmp !== null ? $tmp['id'] : -1);
1546
                }
1547
1548
                // Get denied folders
1549
                $foldersForbidden = [];
1550
                $foldersForbiddenIds = [];
1551
                foreach (explode(';', $record['groupes_interdits']) as $role) {
1552
                    $tmp = DB::queryFirstRow(
1553
                        'SELECT id, title FROM ' . prefixTable('nested_tree') . '
1554
                        WHERE id = %i',
1555
                        $role
1556
                    );
1557
                    array_push($foldersForbidden, $tmp !== null ? $tmp['title'] : $lang->get('none'));
1558
                    array_push($foldersForbiddenIds, $tmp !== null ? $tmp['id'] : -1);
1559
                }
1560
1561
                // Store
1562
                array_push(
1563
                    $arrUsers,
1564
                    array(
1565
                        'id' => $record['id'],
1566
                        'name' => $record['name'],
1567
                        'lastname' => $record['lastname'],
1568
                        'login' => $record['login'],
1569
                        'groups' => implode(', ', $groups),
1570
                        'groupIds' => $groupIds,
1571
                        'managedBy' => $managedBy=== null ? $lang->get('administrator') : $managedBy['title'],
1572
                        'managedById' => $managedBy === null ? 0 : $managedBy['id'],
1573
                        'foldersAllowed' => implode(', ', $foldersAllowed),
1574
                        'foldersAllowedIds' => $foldersAllowedIds,
1575
                        'foldersForbidden' => implode(', ', $foldersForbidden),
1576
                        'foldersForbiddenIds' => $foldersForbiddenIds,
1577
                        'admin' => $record['admin'],
1578
                        'manager' => $record['gestionnaire'],
1579
                        'hr' => $record['can_manage_all_users'],
1580
                        'readOnly' => $record['read_only'],
1581
                        'personalFolder' => $record['personal_folder'],
1582
                        'rootFolder' => $record['can_create_root_folder'],
1583
                    )
1584
                );
1585
            }
1586
1587
            echo prepareExchangedData(
1588
                array(
1589
                    'error' => false,
1590
                    'values' => $arrUsers,
1591
                ),
1592
                'encode'
1593
            );
1594
1595
            break;
1596
1597
            /*
1598
         * UPDATE USERS RIGHTS BY SHARING
1599
         */
1600
        case 'update_users_rights_sharing':
1601
            // Check KEY
1602
            if ($post_key !== $session->get('key')) {
1603
                echo prepareExchangedData(
1604
                    array(
1605
                        'error' => true,
1606
                        'message' => $lang->get('key_is_not_correct'),
1607
                    ),
1608
                    'encode'
1609
                );
1610
                break;
1611
            } elseif ($session->get('user-read_only') === 1) {
1612
                echo prepareExchangedData(
1613
                    array(
1614
                        'error' => true,
1615
                        'message' => $lang->get('error_not_allowed_to'),
1616
                    ),
1617
                    'encode'
1618
                );
1619
                break;
1620
            }
1621
1622
            // Prepare variables
1623
            $data = [
1624
                'source_id' => isset($dataReceived['source_id']) === true ? $dataReceived['source_id'] : 0,
1625
                'destination_ids' => isset($dataReceived['destination_ids']) === true ? $dataReceived['destination_ids'] : 0,
1626
                'user_functions' => isset($dataReceived['user_functions']) === true ? $dataReceived['user_functions'] : '',
1627
                'user_managedby' => isset($dataReceived['user_managedby']) === true ? $dataReceived['user_managedby'] : '',
1628
                'user_fldallowed' => isset($dataReceived['user_fldallowed']) === true ? $dataReceived['user_fldallowed'] : '',
1629
                'user_fldforbid' => isset($dataReceived['user_fldforbid']) === true ? $dataReceived['user_fldforbid'] : '',
1630
                'user_admin' => isset($dataReceived['user_admin']) === true ? $dataReceived['user_admin'] : 0,
1631
                'user_manager' => isset($dataReceived['user_manager']) === true ? $dataReceived['user_manager'] : 0,
1632
                'user_hr' => isset($dataReceived['user_hr']) === true ? $dataReceived['user_hr'] : 0,
1633
                'user_readonly' => isset($dataReceived['user_readonly']) === true ? $dataReceived['user_readonly'] : 1,
1634
                'user_personalfolder' => isset($dataReceived['user_personalfolder']) === true ? $dataReceived['user_personalfolder'] : 0,
1635
                'user_rootfolder' => isset($dataReceived['user_rootfolder']) === true ? $dataReceived['user_rootfolder'] : 0,
1636
            ];
1637
            
1638
            $filters = [
1639
                'source_id' => 'cast:integer',
1640
                'destination_ids' => 'trim|escape',
1641
                'user_functions' => 'trim|escape',
1642
                'user_managedby' => 'trim|escape',
1643
                'user_fldallowed' => 'trim|escape',
1644
                'user_fldforbid' => 'trim|escape',
1645
                'user_admin' => 'cast:integer',
1646
                'user_manager' => 'cast:integer',
1647
                'user_hr' => 'cast:integer',
1648
                'user_readonly' => 'cast:integer',
1649
                'user_personalfolder' => 'cast:integer',
1650
                'user_rootfolder' => 'cast:integer',
1651
            ];
1652
            
1653
            $inputData = dataSanitizer(
1654
                $data,
1655
                $filters
1656
            );
1657
1658
            // Check send values
1659
            if ($inputData['source_id'] === 0 || $inputData['destination_ids'] === 0) {
1660
                // error
1661
                echo prepareExchangedData(
1662
                    array(
1663
                        'error' => true,
1664
                        'message' => $lang->get('error_not_allowed_to'),
1665
                    ),
1666
                    'encode'
1667
                );
1668
            }
1669
1670
            // Get info about user
1671
            $data_user = DB::queryFirstRow(
1672
                'SELECT admin, isAdministratedByRole FROM ' . prefixTable('users') . '
1673
                WHERE id = %i',
1674
                $inputData['source_id']
1675
            );
1676
1677
            // Is this user allowed to do this?
1678
            if (
1679
                (int) $session->get('user-admin') === 1
1680
                || (in_array($data_user['isAdministratedByRole'], $session->get('user-roles_array')))
1681
                || ((int) $session->get('user-can_manage_all_users') === 1 && (int) $data_user['admin'] !== 1)
1682
            ) {
1683
                foreach ($inputData['destination_ids'] as $dest_user_id) {
1684
                    // Is this user allowed to do this?
1685
                    if (
1686
                        (int) $session->get('user-admin') === 1
1687
                        || (in_array($data_user['isAdministratedByRole'], $session->get('user-roles_array')))
1688
                        || ((int) $session->get('user-can_manage_all_users') === 1 && (int) $data_user['admin'] !== 1)
1689
                    ) {
1690
                        // update user
1691
                        DB::update(
1692
                            prefixTable('users'),
1693
                            array(
1694
                                'fonction_id' => str_replace(",", ";", (string) $inputData['user_functions']),
1695
                                'isAdministratedByRole' => $inputData['user_managedby'],
1696
                                'groupes_visibles' => $inputData['user_fldallowed'],
1697
                                'groupes_interdits' => $inputData['user_fldforbid'],
1698
                                'gestionnaire' => $inputData['user_manager'],
1699
                                'read_only' => $inputData['user_readonly'],
1700
                                'can_create_root_folder' => $inputData['user_rootfolder'],
1701
                                'personal_folder' => $inputData['user_personalfolder'],
1702
                                'can_manage_all_users' => $inputData['user_hr'],
1703
                                'admin' => $inputData['user_admin'],
1704
                            ),
1705
                            'id = %i',
1706
                            $dest_user_id
1707
                        );
1708
                    }
1709
                }
1710
            }
1711
1712
            echo prepareExchangedData(
1713
                array(
1714
                    'error' => false,
1715
                ),
1716
                'encode'
1717
            );
1718
1719
            break;
1720
1721
            /*
1722
         * UPDATE USER PROFILE
1723
         */
1724
        case 'user_profile_update':
1725
            // Check KEY
1726
            if ($post_key !== $session->get('key')) {
1727
                echo prepareExchangedData(
1728
                    array(
1729
                        'error' => true,
1730
                        'message' => $lang->get('key_is_not_correct'),
1731
                    ),
1732
                    'encode'
1733
                );
1734
                break;
1735
            }
1736
1737
            // Check user
1738
            if (
1739
                null === $session->get('user-id')
1740
                || empty($session->get('user-id')) === true
1741
            ) {
1742
                echo prepareExchangedData(
1743
                    array(
1744
                        'error' => true,
1745
                        'message' => $lang->get('no_user'),
1746
                    ),
1747
                    'encode'
1748
                );
1749
                break;
1750
            }
1751
1752
            if (empty($dataReceived) === false) {
1753
                // Sanitize
1754
                $data = [
1755
                    'email' => isset($dataReceived['email']) === true ? $dataReceived['email'] : '',
1756
                    'timezone' => isset($dataReceived['timezone']) === true ? $dataReceived['timezone'] : '',
1757
                    'language' => isset($dataReceived['language']) === true ? $dataReceived['language'] : '',
1758
                    'treeloadstrategy' => isset($dataReceived['treeloadstrategy']) === true ? $dataReceived['treeloadstrategy'] : '',
1759
                    'agsescardid' => isset($dataReceived['agsescardid']) === true ? $dataReceived['agsescardid'] : '',
1760
                    'name' => isset($dataReceived['name']) === true ? $dataReceived['name'] : '',
1761
                    'lastname' => isset($dataReceived['lastname']) === true ? $dataReceived['lastname'] : '',
1762
                    'split_view_mode' => isset($dataReceived['split_view_mode']) === true ? $dataReceived['split_view_mode'] : '',
1763
                    'show_subfolders' => isset($dataReceived['show_subfolders']) === true ? $dataReceived['show_subfolders'] : '',
1764
                ];
1765
                
1766
                $filters = [
1767
                    'email' => 'trim|escape',
1768
                    'timezone' => 'trim|escape',
1769
                    'language' => 'trim|escape',
1770
                    'treeloadstrategy' => 'trim|escape',
1771
                    'agsescardid' => 'trim|escape',
1772
                    'name' => 'trim|escape',
1773
                    'lastname' => 'trim|escape',
1774
                    'split_view_mode' => 'cast:integer',
1775
                    'show_subfolders' => 'cast:integer',
1776
                ];
1777
                
1778
                $inputData = dataSanitizer(
1779
                    $data,
1780
                    (array) $filters
1781
                );
1782
1783
                // Prevent LFI.
1784
                $inputData['language'] = preg_replace('/[^a-z_]/', "", $inputData['language']);
1785
1786
                // Force english if non-existent language.
1787
                if (!file_exists(__DIR__."/../includes/language/".$inputData['language'].".php")) {
1788
                    $inputData['language'] = 'english';
1789
                }
1790
1791
                // Data to update
1792
                $update_fields = [
1793
                    'split_view_mode' => $inputData['split_view_mode'],
1794
                    'show_subfolders' => $inputData['show_subfolders'],
1795
                ];
1796
1797
                // Update SETTINGS
1798
                $session->set('user-split_view_mode', (int) $inputData['split_view_mode']);
1799
                $session->set('user-show_subfolders', (int) $inputData['show_subfolders']);
1800
1801
                // User profile edit enabled
1802
                if (($SETTINGS['disable_user_edit_profile'] ?? '0') === '0') {
1803
                    // Update database
1804
                    $update_fields['email']    = $inputData['email'];
1805
                    $update_fields['name']     = $inputData['name'];
1806
                    $update_fields['lastname'] = $inputData['lastname'];
1807
                    // Update session
1808
                    $session->set('user-email', $inputData['email']);
1809
                    $session->set('user-name', $inputData['name']);
1810
                    $session->set('user-lastname', $inputData['lastname']);    
1811
                }
1812
1813
                // User language edit enabled
1814
                if (($SETTINGS['disable_user_edit_language'] ?? '0') === '0') {
1815
                    // Update database
1816
                    $update_fields['user_language'] = $inputData['language'];
1817
                    // Update session
1818
                    $session->set('user-language', $inputData['language']);
1819
                }
1820
1821
                // User timezone edit enabled
1822
                if (($SETTINGS['disable_user_edit_timezone'] ?? '0') === '0') {
1823
                    // Update database
1824
                    $update_fields['usertimezone'] = $inputData['timezone'];
1825
                    // Update session
1826
                    $session->set('user-timezone', $inputData['timezone']);
1827
                }
1828
1829
                // User can edit tree load strategy
1830
                if (($SETTINGS['disable_user_edit_tree_load_strategy'] ?? '0') === '0') {
1831
                    // Update database
1832
                    $update_fields['treeloadstrategy'] = $inputData['treeloadstrategy'];
1833
                    // Update session
1834
                    $session->set('user-tree_load_strategy', $inputData['treeloadstrategy']);
1835
                }
1836
1837
                // update user
1838
                DB::update(
1839
                    prefixTable('users'),
1840
                    $update_fields,
1841
                    'id = %i',
1842
                    $session->get('user-id')
1843
                );
1844
1845
            } else {
1846
                // An error appears on JSON format
1847
                echo prepareExchangedData(
1848
                    array(
1849
                        'error' => true,
1850
                        'message' => $lang->get('json_error_format'),
1851
                    ),
1852
                    'encode'
1853
                );
1854
            }
1855
1856
            // Encrypt data to return
1857
            echo prepareExchangedData(
1858
                array(
1859
                    'error' => false,
1860
                    'message' => '',
1861
                    'name' => $session->get('user-name'),
1862
                    'lastname' => $session->get('user-lastname'),
1863
                    'email' => $session->get('user-email'),
1864
                    'split_view_mode' => $session->get('user-split_view_mode'),
1865
                    'show_subfolders' => $session->get('user-show_subfolders'),
1866
                ),
1867
                'encode'
1868
            );
1869
            break;
1870
1871
            //CASE where refreshing table
1872
        case 'save_user_change':
1873
            // Check KEY
1874
            if ($post_key !== $session->get('key')) {
1875
                echo prepareExchangedData(
1876
                    array(
1877
                        'error' => true,
1878
                        'message' => $lang->get('key_is_not_correct'),
1879
                    ),
1880
                    'encode'
1881
                );
1882
                break;
1883
            } elseif ($session->get('user-read_only') === 1) {
1884
                echo prepareExchangedData(
1885
                    array(
1886
                        'error' => true,
1887
                        'message' => $lang->get('error_not_allowed_to'),
1888
                    ),
1889
                    'encode'
1890
                );
1891
                break;
1892
            }
1893
1894
            // prepare variables
1895
            $post_user_id = filter_var($dataReceived['user_id'], FILTER_SANITIZE_NUMBER_INT);
1896
            $post_field = filter_var($dataReceived['field'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
1897
            $post_new_value = filter_var($dataReceived['value'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
1898
            $post_context = filter_var($dataReceived['context'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
1899
1900
            // If
1901
            if (empty($post_context) === false && $post_context === 'add_one_role_to_user') {
1902
                $data_user = DB::queryFirstRow(
1903
                    'SELECT fonction_id, public_key
1904
                    FROM ' . prefixTable('users') . '
1905
                    WHERE id = %i',
1906
                    $post_user_id
1907
                );
1908
1909
                if ($data_user) {
1910
                    // Ensure array is unique
1911
                    $post_new_value = str_replace(',', ';', $data_user['fonction_id']) . ';' . $post_new_value;
1912
                    $post_new_value = implode(';', array_unique(explode(';', $post_new_value)));
1913
                } else {
1914
                    // User not found
1915
                    echo prepareExchangedData(
1916
                        array(
1917
                            'error' => true,
1918
                            'message' => $lang->get('user_not_exists'),
1919
                        ),
1920
                        'encode'
1921
                    );
1922
                    break;
1923
                }
1924
            }
1925
1926
            // Manage specific case of api key
1927
            if($post_field === 'user_api_key') {
1928
                $encrypted_key = encryptUserObjectKey(base64_encode($post_new_value), $session->get('user-public_key'));
1929
                $session->set('user-api_key', $post_new_value);
1930
1931
                // test if user has an api key
1932
                $data_user = DB::queryFirstRow(
1933
                    'SELECT value
1934
                    FROM ' . prefixTable('api') . '
1935
                    WHERE user_id = %i',
1936
                    $post_user_id
1937
                );
1938
                if ($data_user) {
1939
                    // update
1940
                    DB::update(
1941
                        prefixTable('api'),
1942
                        array(
1943
                            'value' => $encrypted_key,
1944
                            'timestamp' => time()
1945
                        ),
1946
                        'user_id = %i',
1947
                        $post_user_id
1948
                    );
1949
                } else {
1950
                    // insert
1951
                    DB::insert(
1952
                        prefixTable('api'),
1953
                        array(
1954
                            'type' => 'user',
1955
                            'user_id' => $post_user_id,
1956
                            'value' => $encrypted_key,
1957
                            'timestamp' => time()
1958
                        )
1959
                    );
1960
                }
1961
1962
                // send data
1963
                echo prepareExchangedData(
1964
                    array(
1965
                        'error' => false,
1966
                        'message' => ''
1967
                    ),
1968
                    'encode'
1969
                );
1970
1971
                break;
1972
            }
1973
1974
            DB::update(
1975
                prefixTable('users'),
1976
                array(
1977
                    $post_field => $post_new_value,
1978
                ),
1979
                'id = %i',
1980
                $post_user_id
1981
            );
1982
1983
            // special case
1984
            if ($post_field === 'auth_type' && $post_new_value === 'ldap') {
1985
                /*DB::update(
1986
                    prefixTable('users'),
1987
                    array(
1988
                        'special' => 'recrypt-private-key',
1989
                    ),
1990
                    'id = %i',
1991
                    $post_user_id
1992
                );*/
1993
            }
1994
1995
            // send data
1996
            echo prepareExchangedData(
1997
                array(
1998
                    'error' => false,
1999
                    'message' => ''
2000
                ),
2001
                'encode'
2002
            );
2003
2004
            break;
2005
2006
        /*
2007
        * GET LDAP LIST OF USERS
2008
        */
2009
        case 'get_list_of_users_in_ldap':
2010
            // Check KEY
2011
            if ($post_key !== $session->get('key')) {
2012
                echo prepareExchangedData(
2013
                    array(
2014
                        'error' => true,
2015
                        'message' => $lang->get('key_is_not_correct'),
2016
                    ),
2017
                    'encode'
2018
                );
2019
                break;
2020
            }
2021
            
2022
            // Build ldap configuration array
2023
            $config = [
2024
                // Mandatory Configuration Options
2025
                'hosts'            => explode(',', (string) $SETTINGS['ldap_hosts']),
2026
                'base_dn'          => $SETTINGS['ldap_bdn'],
2027
                'username'         => $SETTINGS['ldap_username'],
2028
                'password'         => $SETTINGS['ldap_password'],
2029
            
2030
                // Optional Configuration Options
2031
                'port'             => $SETTINGS['ldap_port'],
2032
                'use_ssl'          => (int) $SETTINGS['ldap_ssl'] === 1 ? true : false,
2033
                'use_tls'          => (int) $SETTINGS['ldap_tls'] === 1 ? true : false,
2034
                'version'          => 3,
2035
                'timeout'          => 5,
2036
                'follow_referrals' => false,
2037
            
2038
                // Custom LDAP Options
2039
                'options' => [
2040
                    // See: http://php.net/ldap_set_option
2041
                    LDAP_OPT_X_TLS_REQUIRE_CERT => isset($SETTINGS['ldap_tls_certificate_check']) === false ? 'LDAP_OPT_X_TLS_NEVER' : $SETTINGS['ldap_tls_certificate_check'],
2042
                ]
2043
            ];
2044
            //prepare connection
2045
            $connection = new Connection($config);
2046
2047
            // Connect to LDAP
2048
            try {
2049
                $connection->connect();
2050
            
2051
            } catch (\LdapRecord\Auth\BindException $e) {
2052
                $error = $e->getDetailedError();
2053
                if ($error && defined('LOG_TO_SERVER') && LOG_TO_SERVER === true) {
2054
                    error_log('TEAMPASS Error - LDAP - '.$error->getErrorCode()." - ".$error->getErrorMessage(). " - ".$error->getDiagnosticMessage());
2055
                }
2056
                // deepcode ignore ServerLeak: No important data is sent and it is encrypted before sending
2057
                echo prepareExchangedData(
2058
                    array(
2059
                        'error' => true,
2060
                        'message' => "An error occurred.",
2061
                    ),
2062
                    'encode'
2063
                );
2064
                break;
2065
            }
2066
2067
            $adUsersToSync = array();
2068
            $adRoles = array();
2069
            $usersAlreadyInTeampass = array();
2070
            $adUsedAttributes = array(
2071
                'dn', 'mail', 'givenname', 'samaccountname', 'sn', $SETTINGS['ldap_user_attribute'],
2072
                'memberof', 'name', 'displayname', 'cn', 'shadowexpire', 'distinguishedname'
2073
            );
2074
2075
            try {
2076
                $results = $connection->query()
2077
                    ->rawfilter($SETTINGS['ldap_user_object_filter'])
2078
                    ->in((empty($SETTINGS['ldap_dn_additional_user_dn']) === false ? $SETTINGS['ldap_dn_additional_user_dn'].',' : '').$SETTINGS['ldap_bdn'])
2079
                    ->whereHas($SETTINGS['ldap_user_attribute'])
2080
                    ->paginate(100);
2081
            } catch (\LdapRecord\Auth\BindException $e) {
2082
                $error = $e->getDetailedError();
2083
                if ($error && defined('LOG_TO_SERVER') && LOG_TO_SERVER === true) {
2084
                    error_log('TEAMPASS Error - LDAP - '.$error->getErrorCode()." - ".$error->getErrorMessage(). " - ".$error->getDiagnosticMessage());
2085
                }
2086
                // deepcode ignore ServerLeak: No important data is sent and it is encrypted before sending
2087
                echo prepareExchangedData(
2088
                    array(
2089
                        'error' => true,
2090
                        'message' => "An error occurred.",
2091
                    ),
2092
                    'encode'
2093
                );
2094
                break;
2095
            }
2096
            
2097
            foreach ($results as $adUser) {
2098
                if (isset($adUser[$SETTINGS['ldap_user_attribute']][0]) === false) continue;
2099
                // Build the list of all groups in AD
2100
                if (isset($adUser['memberof']) === true) {
2101
                    foreach($adUser['memberof'] as $j => $adUserGroup) {
2102
                        if (empty($adUserGroup) === false && $j !== "count") {
2103
                            $adGroup = substr($adUserGroup, 3, strpos($adUserGroup, ',') - 3);
2104
                            if (in_array($adGroup, $adRoles) === false && empty($adGroup) === false) {
2105
                                array_push($adRoles, $adGroup);
2106
                            }
2107
                        }
2108
                    }
2109
                }
2110
2111
                // Is user in Teampass ?
2112
                $userLogin = $adUser[$SETTINGS['ldap_user_attribute']][0];
2113
                if (null !== $userLogin) {
2114
                    // Get his ID
2115
                    $userInfo = DB::queryFirstRow(
2116
                        'SELECT id, login, fonction_id, auth_type
2117
                        FROM ' . prefixTable('users') . '
2118
                        WHERE login = %s',
2119
                        $userLogin
2120
                    );
2121
                    // Loop on all user attributes
2122
                    $tmp = [
2123
                        'userInTeampass' => DB::count() > 0 ? (int) $userInfo['id'] : DB::count(),
2124
                        'userAuthType' => isset($userInfo['auth_type']) === true ? $userInfo['auth_type'] : 0,                        
2125
                    ];
2126
                    foreach ($adUsedAttributes as $userAttribute) {
2127
                        if (isset($adUser[$userAttribute]) === true) {
2128
                            if (is_array($adUser[$userAttribute]) === true && array_key_first($adUser[$userAttribute]) !== 'count') {
2129
                                // Loop on all entries
2130
                                $tmpAttrValue = '';
2131
                                foreach ($adUser[$userAttribute] as $userAttributeEntry) {
2132
                                    if ($userAttribute === 'memberof') {
2133
                                        $userAttributeEntry = substr($userAttributeEntry, 3, strpos($userAttributeEntry, ',') - 3);
2134
                                    }
2135
                                    if (empty($tmpAttrValue) === true) {
2136
                                        $tmpAttrValue = $userAttributeEntry;
2137
                                    } else {
2138
                                        $tmpAttrValue .= ','.$userAttributeEntry;
2139
                                    }
2140
                                }
2141
                                $tmp[$userAttribute] = $tmpAttrValue;
2142
                            } else {
2143
                                $tmp[$userAttribute] = $adUser[$userAttribute];
2144
                            }
2145
                        }
2146
                    }
2147
                    array_push($adUsersToSync, $tmp);
2148
                }
2149
            }
2150
2151
            // Get all groups in Teampass
2152
            $teampassRoles = array();
2153
            $rows = DB::query('SELECT id,title FROM ' . prefixTable('roles_title'));
2154
            foreach ($rows as $record) {
2155
                array_push(
2156
                    $teampassRoles,
2157
                    array(
2158
                        'id' => $record['id'],
2159
                        'title' => $record['title']
2160
                    )
2161
                );
2162
            }
2163
2164
            echo (string) prepareExchangedData(
2165
                array(
2166
                    'error' => false,
2167
                    'entries' => $adUsersToSync,
2168
                    'ldap_groups' => $adRoles,
2169
                    'teampass_groups' => $teampassRoles,
2170
                    'usersAlreadyInTeampass' => $usersAlreadyInTeampass,
2171
                ), 
2172
                'encode'
2173
            );
2174
2175
            break;
2176
2177
        /*
2178
         * ADD USER FROM LDAP OR OAUTH2
2179
         */
2180
        case 'add_user_from_ad':
2181
            // Check KEY
2182
            if ($post_key !== $session->get('key')) {
2183
                echo prepareExchangedData(
2184
                    array(
2185
                        'error' => true,
2186
                        'message' => $lang->get('key_is_not_correct'),
2187
                    ),
2188
                    'encode'
2189
                );
2190
                break;
2191
            }
2192
2193
            // Prepare variables
2194
            $post_login = filter_var($dataReceived['login'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
2195
            $post_name = filter_var($dataReceived['name'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
2196
            $post_lastname = filter_var($dataReceived['lastname'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
2197
            $post_email = filter_var($dataReceived['email'], FILTER_SANITIZE_EMAIL);
2198
            $post_roles = filter_var_array(
2199
                $dataReceived['roles'],
2200
                FILTER_SANITIZE_NUMBER_INT
2201
            );
2202
            $post_authType = filter_var($dataReceived['authType'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
2203
2204
            // Empty user
2205
            if (empty($post_login) === true || empty($post_email) === true) {
2206
                echo prepareExchangedData(
2207
                    array(
2208
                        'error' => true,
2209
                        'message' => $lang->get('user_must_have_login_and_email'),
2210
                    ),
2211
                    'encode'
2212
                );
2213
                break;
2214
            }
2215
            // Check if user already exists
2216
            $data = DB::query(
2217
                'SELECT id, fonction_id, groupes_interdits, groupes_visibles
2218
                FROM ' . prefixTable('users') . '
2219
                WHERE login = %s',
2220
                $post_login
2221
            );
2222
2223
            if (DB::count() === 0) {
2224
                // check if admin role is set. If yes then check if originator is allowed
2225
                if ((int) $session->get('user-admin') !== 1 && (int) $session->get('user-manager') !== 1) {
2226
                    echo prepareExchangedData(
2227
                        array(
2228
                            'error' => true,
2229
                            'message' => $lang->get('error_empty_data'),
2230
                        ),
2231
                        'encode'
2232
                    );
2233
                    break;
2234
                }
2235
2236
                // load password library
2237
                $passwordManager = new PasswordManager();
2238
2239
                // Prepare variables
2240
                $password = generateQuickPassword(12, true);
2241
                $hashedPassword = $passwordManager->hashPassword($password);
2242
                if ($passwordManager->verifyPassword($hashedPassword, $password) === false) {
2243
                    echo prepareExchangedData(
2244
                        array(
2245
                            'error' => true,
2246
                            'message' => $lang->get('error_not_allowed_to'),
2247
                        ),
2248
                        'encode'
2249
                    );
2250
                    break;
2251
                }
2252
            } else {
2253
                echo prepareExchangedData(
2254
                    array(
2255
                        'error' => true,
2256
                        'message' => $lang->get('error_user_exists'),
2257
                    ),
2258
                    'encode'
2259
                );
2260
                break;
2261
            }
2262
2263
            
2264
            // We need to create his keys with transparent recovery support
2265
            $userKeys = generateUserKeys($password, $SETTINGS);
2266
2267
            // Prepare user data for insertion
2268
            $userData = array(
2269
                'login' => $post_login,
2270
                'pw' => $hashedPassword,
2271
                'email' => $post_email,
2272
                'name' => $post_name,
2273
                'lastname' => $post_lastname,
2274
                'admin' => '0',
2275
                'gestionnaire' => '0',
2276
                'can_manage_all_users' => '0',
2277
                'personal_folder' => (int) $SETTINGS['enable_pf_feature'] === 1 ? 1 : 0,
2278
                'fonction_id' => implode(';', $post_roles),
2279
                'groupes_interdits' => '',
2280
                'groupes_visibles' => '',
2281
                'last_pw_change' => time(),
2282
                'user_language' => $SETTINGS['default_language'],
2283
                'encrypted_psk' => '',
2284
                'isAdministratedByRole' => (isset($SETTINGS['oauth_new_user_is_administrated_by']) === true && empty($SETTINGS['oauth_new_user_is_administrated_by']) === false) ? $SETTINGS['oauth_new_user_is_administrated_by'] : 0,
2285
                'public_key' => $userKeys['public_key'],
2286
                'private_key' => $userKeys['private_key'],
2287
                'special' => 'user_added_from_ad',
2288
                'auth_type' => $post_authType,
2289
                'is_ready_for_usage' => isset($SETTINGS['enable_tasks_manager']) === true && (int) $SETTINGS['enable_tasks_manager'] === 1 ? 0 : 1,
2290
                'created_at' => time(),
2291
            );
2292
2293
            // Add transparent recovery fields if available
2294
            if (isset($userKeys['user_seed'])) {
2295
                $userData['user_derivation_seed'] = $userKeys['user_seed'];
2296
                $userData['private_key_backup'] = $userKeys['private_key_backup'];
2297
                $userData['key_integrity_hash'] = $userKeys['key_integrity_hash'];
2298
                $userData['last_pw_change'] = time();
2299
            }
2300
2301
            // Insert user in DB
2302
            DB::insert(
2303
                prefixTable('users'),
2304
                $userData
2305
            );
2306
            $newUserId = DB::insertId();
2307
2308
            // Create the API key
2309
            DB::insert(
2310
                prefixTable('api'),
2311
                array(
2312
                    'type' => 'user',
2313
                    //'label' => $newUserId,
2314
                    'value' => encryptUserObjectKey(base64_encode(uniqidReal(39)), $userKeys['public_key']),
2315
                    'timestamp' => time(),
2316
                    'user_id' => $newUserId,
2317
                    'allowed_folders' => '',
2318
                )
2319
            );
2320
2321
            // Create personnal folder
2322
            if (isset($SETTINGS['enable_pf_feature']) === true && (int) $SETTINGS['enable_pf_feature'] === 1) {
2323
                DB::insert(
2324
                    prefixTable('nested_tree'),
2325
                    array(
2326
                        'parent_id' => '0',
2327
                        'title' => $newUserId,
2328
                        'bloquer_creation' => '0',
2329
                        'bloquer_modification' => '0',
2330
                        'personal_folder' => '1',
2331
                        'fa_icon' => 'fas fa-folder',
2332
                        'fa_icon_selected' => 'fas fa-folder-open',
2333
                        'categories' => '',
2334
                    )
2335
                );
2336
2337
                // Rebuild tree
2338
                $tree = new NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
2339
                $tree->rebuild();
2340
            }
2341
2342
            // Send email to new user
2343
            if (isset($SETTINGS['enable_tasks_manager']) === false || (int) $SETTINGS['enable_tasks_manager'] === 0) {
2344
                $emailSettings = new EmailSettings($SETTINGS);
2345
                $emailService = new EmailService();
2346
                $emailService->sendMail(
2347
                    $lang->get('email_subject_new_user'),
2348
                    str_replace(
2349
                        array('#tp_login#', '#enc_code#', '#tp_link#'),
2350
                        array(addslashes($post_login), addslashes($password), $SETTINGS['email_server_url']),
2351
                        $lang->get('email_body_user_added_from_ldap_encryption_code')
2352
                    ),
2353
                    $post_email,
2354
                    $emailSettings
2355
                );
2356
            }
2357
2358
            echo prepareExchangedData(
2359
                array(
2360
                    'error' => false,
2361
                    'message' => '',
2362
                    'user_id' => $newUserId,
2363
                    'user_code' => $password,
2364
                    'visible_otp' => ADMIN_VISIBLE_OTP_ON_LDAP_IMPORT,
2365
                    'post_action' => isset($SETTINGS['enable_tasks_manager']) === true && (int) $SETTINGS['enable_tasks_manager'] === 1 ? 'prepare_tasks' : 'encrypt_keys',
2366
                ),
2367
                'encode'
2368
            );
2369
2370
            break;
2371
2372
        /*
2373
         * CHANGE USER AUTHENTICATION TYPE
2374
         */
2375
        case 'change_user_auth_type':
2376
            // Check KEY
2377
            if ($post_key !== $session->get('key')) {
2378
                echo prepareExchangedData(
2379
                    array(
2380
                        'error' => true,
2381
                        'message' => $lang->get('key_is_not_correct'),
2382
                    ),
2383
                    'encode'
2384
                );
2385
                break;
2386
            }
2387
2388
            // Prepare variables
2389
            $post_id = filter_var($dataReceived['user_id'], FILTER_SANITIZE_NUMBER_INT);
2390
            $post_auth = filter_var($dataReceived['auth_type'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
2391
2392
            // Empty user
2393
            if (empty($post_id) === true) {
2394
                echo prepareExchangedData(
2395
                    array(
2396
                        'error' => true,
2397
                        'message' => $lang->get('user_not_exists'),
2398
                    ),
2399
                    'encode'
2400
                );
2401
                break;
2402
            }
2403
            // Check if user already exists
2404
            DB::query(
2405
                'SELECT id
2406
                FROM ' . prefixTable('users') . '
2407
                WHERE id = %i',
2408
                $post_id
2409
            );
2410
2411
            if (DB::count() > 0) {
2412
                // Change authentication type in DB
2413
                DB::update(
2414
                    prefixTable('users'),
2415
                    array(
2416
                        'auth_type' => $post_auth,
2417
                    ),
2418
                    'id = %i',
2419
                    $post_id
2420
                );
2421
            } else {
2422
                echo prepareExchangedData(
2423
                    array(
2424
                        'error' => true,
2425
                        'message' => $lang->get('user_not_exists'),
2426
                    ),
2427
                    'encode'
2428
                );
2429
                break;
2430
            }
2431
2432
            echo prepareExchangedData(
2433
                array(
2434
                    'message' => '',
2435
                    'error' => false,
2436
                ),
2437
                'encode'
2438
            );
2439
2440
            break;
2441
        
2442
2443
        /*
2444
        * GET OAUTH2 LIST OF USERS
2445
        */
2446
        case 'get_list_of_users_in_oauth2':
2447
            // Check KEY
2448
            if ($post_key !== $session->get('key')) {
2449
                echo prepareExchangedData(
2450
                    array(
2451
                        'error' => true,
2452
                        'message' => $lang->get('key_is_not_correct'),
2453
                    ),
2454
                    'encode'
2455
                );
2456
                break;
2457
            }
2458
2459
            // Création d'une instance du contrôleur
2460
            $OAuth2 = new OAuth2Controller($SETTINGS);
2461
2462
            // Traitement de la réponse de callback Azure
2463
            $usersList = $OAuth2->getAllUsers();            
2464
2465
            // Get all groups in Teampass
2466
            $teampassRoles = array();
2467
            $titleToIdMap = [];
2468
            $rows = DB::query('SELECT id,title FROM ' . prefixTable('roles_title'));
2469
            foreach ($rows as $record) {
2470
                array_push(
2471
                    $teampassRoles,
2472
                    array(
2473
                        'id' => $record['id'],
2474
                        'title' => $record['title']
2475
                    )
2476
                );
2477
                $titleToIdMap[$record['title']] = $record['id'];
2478
            }
2479
2480
            // Do init
2481
            $adUsersToSync = [];
2482
            $adRoles = [];
2483
            $usersAlreadyInTeampass = [];
2484
2485
            function nameFromEmail($email) {
2486
                // Utiliser une expression régulière pour extraire le texte avant le domaine
2487
                if (preg_match('/^(.+)@/', $email, $matches)) {
2488
                    return $matches[1];
2489
                } else {
2490
                    return false;
2491
                }
2492
            }
2493
            
2494
            foreach ($usersList as $oAuthUser) {
2495
                // Build the list of all groups in AD
2496
                if (isset($oAuthUser['groups']) === true) {
2497
                    foreach ($oAuthUser['groups'] as $group) {
2498
                        if (
2499
                            isset($group['displayName']) && !in_array($group['displayName'], $adRoles)
2500
                            && $SETTINGS['oauth_self_register_groups'] !== $group['displayName']
2501
                        ) {
2502
                            $adRoles[] = $group['displayName'];
2503
                        }
2504
                    }
2505
                }
2506
2507
                // Is user in Teampass ?
2508
                $userLogin = nameFromEmail($oAuthUser['userPrincipalName']);
2509
                if (null !== $userLogin) {
2510
                    //error_log(print_r($oAuthUser,true));
2511
                    // Get his ID
2512
                    $userInfo = DB::queryFirstRow(
2513
                        'SELECT id, login, fonction_id, auth_type
2514
                        FROM ' . prefixTable('users') . '
2515
                        WHERE login = %s',
2516
                        $userLogin
2517
                    );
2518
                    // Get array of groups
2519
                    $userGroupsInTeampass = explode(';', (string) is_null($userInfo) ? '' : $userInfo['fonction_id']);
2520
                    // Loop on all user attributes
2521
                    $userADInfos = [
2522
                        'userInTeampass' => isset($userInfo) ? (int) $userInfo['id'] : 0,
2523
                        'userAuthType' => isset($userInfo) ? $userInfo['auth_type'] : 0,     
2524
                        'login' => $userLogin,
2525
                        'mail' => '',
2526
                    ];
2527
                    foreach ($oAuthUser as $key => $value) {
2528
                        if ($key !== 'groups') {
2529
                            $userADInfos[$key] = $value;
2530
                        } else {
2531
                            $userADInfos[$key] = array_column($value, 'displayName');
2532
                        }
2533
                    }
2534
2535
                    // Mettre à jour $user['groups']
2536
                    $updatedGroups = array();
2537
                    foreach ($userADInfos['groups'] as $groupName) {
2538
                        if (isset($titleToIdMap[$groupName])) {
2539
                            $updatedGroups[] = array(
2540
                                'name' => $groupName,
2541
                                'id' => $titleToIdMap[$groupName],
2542
                                'insideGroupInTeampass' => in_array($titleToIdMap[$groupName], $userGroupsInTeampass) ? 1 : 0,
2543
                            );
2544
                        } else {
2545
                            $updatedGroups[] = array(
2546
                                'name' => $groupName,
2547
                                'id' => null,
2548
                                'insideGroupInTeampass' => 0,
2549
                            );
2550
                        }
2551
                    }
2552
2553
                    // Mettre à jour $user['groups'] avec les nouveaux groupes
2554
                    $userADInfos['groups'] = $updatedGroups;
2555
                    array_push($adUsersToSync, $userADInfos);
2556
                }
2557
            }
2558
2559
            echo (string) prepareExchangedData(
2560
                array(
2561
                    'error' => false,
2562
                    'ad_users' => $adUsersToSync,
2563
                    'ad_groups' => $adRoles,
2564
                    'teampass_groups' => $teampassRoles,
2565
                ), 
2566
                'encode'
2567
            );
2568
2569
            break;
2570
2571
        /*
2572
         * CHANGE USER DISABLE
2573
         */
2574
        case 'manage_user_disable_status':
2575
            // Check KEY
2576
            if ($post_key !== $session->get('key')) {
2577
                echo prepareExchangedData(
2578
                    array(
2579
                        'error' => true,
2580
                        'message' => $lang->get('key_is_not_correct'),
2581
                    ),
2582
                    'encode'
2583
                );
2584
                break;
2585
            }
2586
2587
            // Is this user allowed to do this?
2588
            if (
2589
                (int) $session->get('user-admin') !== 1
2590
                && (int) $session->get('user-can_manage_all_users') !== 1
2591
            ) {
2592
                echo prepareExchangedData(
2593
                    array(
2594
                        'error' => true,
2595
                        'message' => $lang->get('error_not_allowed_to'),
2596
                    ),
2597
                    'encode'
2598
                );
2599
                break;
2600
            }
2601
2602
            // Prepare variables
2603
            $post_id = filter_var($dataReceived['user_id'], FILTER_SANITIZE_NUMBER_INT);
2604
            $post_user_disabled = filter_var($dataReceived['disabled_status'], FILTER_SANITIZE_NUMBER_INT);
2605
2606
2607
            // Empty user
2608
            if (empty($post_id) === true) {
2609
                echo prepareExchangedData(
2610
                    array(
2611
                        'error' => true,
2612
                        'message' => $lang->get('user_not_exists'),
2613
                    ),
2614
                    'encode'
2615
                );
2616
                break;
2617
            }
2618
            // Check if user already exists
2619
            DB::query(
2620
                'SELECT id
2621
                FROM ' . prefixTable('users') . '
2622
                WHERE id = %i',
2623
                $post_id
2624
            );
2625
2626
            if (DB::count() > 0) {
2627
                // Change authentication type in DB
2628
                DB::update(
2629
                    prefixTable('users'),
2630
                    array(
2631
                        'disabled' => empty($post_user_disabled) === true ? 0 : $post_user_disabled,
2632
                    ),
2633
                    'id = %i',
2634
                    $post_id
2635
                );
2636
2637
                // update LOG
2638
                logEvents(
2639
                    $SETTINGS,
2640
                    'user_mngt',
2641
                    $post_user_disabled === 1 ? 'at_user_locked' : 'at_user_unlocked',
2642
                    (string) $session->get('user-id'),
2643
                    $session->get('user-login'),
2644
                    $post_id
2645
                );
2646
            } else {
2647
                echo prepareExchangedData(
2648
                    array(
2649
                        'error' => true,
2650
                        'message' => $lang->get('user_not_exists'),
2651
                    ),
2652
                    'encode'
2653
                );
2654
                break;
2655
            }
2656
2657
            echo prepareExchangedData(
2658
                array(
2659
                    'message' => '',
2660
                    'error' => false,
2661
                ),
2662
                'encode'
2663
            );
2664
2665
            break;
2666
2667
        case "create_new_user_tasks":
2668
            // Check KEY
2669
            if ($post_key !== $session->get('key')) {
2670
                echo prepareExchangedData(
2671
                    array(
2672
                        'error' => true,
2673
                        'message' => $lang->get('key_is_not_correct'),
2674
                    ),
2675
                    'encode'
2676
                );
2677
                break;
2678
            }
2679
2680
            // Prepare variables
2681
            $post_user_id = filter_var($dataReceived['user_id'], FILTER_SANITIZE_NUMBER_INT);
2682
            $post_user_code = filter_var($dataReceived['user_code'], FILTER_SANITIZE_FULL_SPECIAL_CHARS);
2683
2684
            // Search TP_USER in db        
2685
            $userTP = DB::queryFirstRow(
2686
                'SELECT pw
2687
                FROM ' . prefixTable('users') . '
2688
                WHERE id = %i',
2689
                TP_USER_ID
2690
            );
2691
            if (DB::count() === 0) {
2692
                return prepareExchangedData(
2693
                    array(
2694
                        'error' => true,
2695
                        'message' => 'User not exists',
2696
                    ),
2697
                    'encode'
2698
                );
2699
            }
2700
2701
            // Create process
2702
            DB::insert(
2703
                prefixTable('background_tasks'),
2704
                array(
2705
                    'created_at' => time(),
2706
                    'process_type' => 'create_user_keys',
2707
                    'arguments' => json_encode([
2708
                        'new_user_id' => (int) $post_user_id,
2709
                        'new_user_pwd' => '',
2710
                        'new_user_code' => cryption($post_user_code, '','encrypt', $SETTINGS)['string'],
2711
                        'owner_id' => (int) TP_USER_ID,
2712
                        'creator_pwd' => $userTP['pw'],
2713
                        'email_body' => $lang->get('email_body_user_config_5'),
2714
                        'send_email' => 1,
2715
                        'otp_provided_new_value' => 0,
2716
                        'user_self_change' => 0,
2717
                    ]),
2718
                    'updated_at' => '',
2719
                    'finished_at' => '',
2720
                    'output' => '',
2721
                )
2722
            );
2723
            $processId = DB::insertId();
2724
2725
            // Create tasks
2726
            createUserTasks(
2727
                $processId,
2728
                isset($SETTINGS['maximum_number_of_items_to_treat']) === true ? $SETTINGS['maximum_number_of_items_to_treat'] : NUMBER_ITEMS_IN_BATCH
2729
            );
2730
2731
            // Generate user keys with the code and transparent recovery support
2732
            $userKeys = generateUserKeys($post_user_code, $SETTINGS);
2733
2734
            // Prepare update data
2735
            $updateData = array(
2736
                'is_ready_for_usage' => 1,
2737
                'otp_provided' => 0,
2738
                'ongoing_process_id' => $processId,
2739
                'special' => 'generate-keys',
2740
                'public_key' => $userKeys['public_key'],
2741
                'private_key' => $userKeys['private_key'],
2742
                // Notify user that he must re download his keys:
2743
                'keys_recovery_time' => NULL,
2744
            );
2745
2746
            // Add transparent recovery fields if available
2747
            if (isset($userKeys['user_seed'])) {
2748
                $updateData['user_derivation_seed'] = $userKeys['user_seed'];
2749
                $updateData['private_key_backup'] = $userKeys['private_key_backup'];
2750
                $updateData['key_integrity_hash'] = $userKeys['key_integrity_hash'];
2751
                $updateData['last_pw_change'] = time();
2752
            }
2753
2754
            // Update user
2755
            DB::update(
2756
                prefixTable('users'),
2757
                $updateData,
2758
                'id = %i',
2759
                $post_user_id
2760
            );
2761
2762
            echo prepareExchangedData(
2763
                array(
2764
                    'message' => '',
2765
                    'error' => false,
2766
                ),
2767
                'encode'
2768
            );
2769
2770
            break;
2771
2772
        /*
2773
        * WHAT IS THE PROGRESS OF GENERATING NEW KEYS AND OTP FOR A USER
2774
        */
2775
        case 'get_generate_keys_progress':
2776
            // Check KEY
2777
            if ($post_key !== $session->get('key')) {
2778
                echo prepareExchangedData(
2779
                    array(
2780
                        'error' => true,
2781
                        'message' => $lang->get('key_is_not_correct'),
2782
                    ),
2783
                    'encode'
2784
                );
2785
                break;
2786
            } elseif ($session->get('user-read_only') === 1) {
2787
                echo prepareExchangedData(
2788
                    array(
2789
                        'error' => true,
2790
                        'message' => $lang->get('error_not_allowed_to'),
2791
                    ),
2792
                    'encode'
2793
                );
2794
                break;
2795
            }
2796
2797
            if (isset($dataReceived['user_id']) === false) {
2798
                // Exit nothing to be done
2799
                echo prepareExchangedData(
2800
                    array(
2801
                        'error' => true,
2802
                        'message' => '',
2803
                        'user_id' => '',
2804
                        'status' => '',
2805
                        'debug' => '',
2806
                    ),
2807
                    'encode'
2808
                );
2809
            }
2810
2811
            // Prepare variables
2812
            $user_id = filter_var($dataReceived['user_id'], FILTER_SANITIZE_NUMBER_INT);
2813
2814
            // get user info
2815
            $processesProgress = DB::query(
2816
                'SELECT u.ongoing_process_id, pt.task, pt.updated_at, pt.finished_at, pt.is_in_progress
2817
                FROM ' . prefixTable('users') . ' AS u
2818
                INNER JOIN ' . prefixTable('background_subtasks') . ' AS pt ON (pt.task_id = u.ongoing_process_id)
2819
                WHERE u.id = %i',
2820
                $user_id
2821
            );
2822
2823
            $finished_steps = 0;
2824
            $nb_steps = count($processesProgress);
2825
            foreach($processesProgress as $process) {
2826
                if ((int) $process['is_in_progress'] === -1) {
2827
                    $finished_steps ++;
2828
                }
2829
            }
2830
2831
            echo prepareExchangedData(
2832
                array(
2833
                    'error' => false,
2834
                    'message' => '',
2835
                    'user_id' => $user_id,
2836
                    'status' => $finished_steps === $nb_steps ? 'finished' : number_format($finished_steps/$nb_steps*100, 0).'%',
2837
                    'debug' => $finished_steps.",".$nb_steps,
2838
                ),
2839
                'encode'
2840
            );
2841
2842
            break;
2843
2844
2845
        /**
2846
         * CHECK IF USER IS FINISHED WITH GENERATING NEW KEYS AND OTP FOR A USER
2847
         */
2848
        case "get_user_infos":
2849
            // Check KEY
2850
            if ($post_key !== $session->get('key')) {
2851
                echo prepareExchangedData(
2852
                    array(
2853
                        'error' => true,
2854
                        'message' => $lang->get('key_is_not_correct'),
2855
                    ),
2856
                    'encode'
2857
                );
2858
                break;
2859
            } elseif ($session->get('user-read_only') === 1) {
2860
                echo prepareExchangedData(
2861
                    array(
2862
                        'error' => true,
2863
                        'message' => $lang->get('error_not_allowed_to'),
2864
                    ),
2865
                    'encode'
2866
                );
2867
                break;
2868
            }
2869
2870
            // Prepare variables
2871
            $user_id = filter_var($dataReceived['user_id'], FILTER_SANITIZE_NUMBER_INT);
2872
2873
            $fullUserInfos = getFullUserInfos((int) $user_id);
2874
2875
            // Filter only on useful fields
2876
            $userInfos['id'] = $fullUserInfos['id'];
2877
            $userInfos['ongoing_process_id'] = $fullUserInfos['ongoing_process_id'];
2878
2879
            echo prepareExchangedData(
2880
                array(
2881
                    'error' => false,
2882
                    'message' => '',
2883
                    'user_id' => $user_id,
2884
                    'user_infos' => $userInfos,
2885
                    'debug' => '',
2886
                ),
2887
                'encode'
2888
            );
2889
2890
            break;
2891
        
2892
        case "reset_antibruteforce":
2893
            // Check KEY
2894
            if ($post_key !== $session->get('key')) {
2895
                echo prepareExchangedData(
2896
                    array(
2897
                        'error' => true,
2898
                        'message' => $lang->get('key_is_not_correct'),
2899
                    ),
2900
                    'encode'
2901
                );
2902
                break;
2903
            }
2904
2905
            // Prepare variables
2906
            $login = getFullUserInfos((int) $dataReceived['user_id'])['login'];
2907
2908
            // Delete all logs for this user
2909
            DB::delete(
2910
                prefixTable('auth_failures'),
2911
                'source = %s AND value = %s',
2912
                'login',
2913
                $login
2914
            );
2915
            
2916
            break;
2917
        
2918
        case "list_deleted_users":
2919
            // Check KEY
2920
            if ($post_key !== $session->get('key')) {
2921
                echo prepareExchangedData(
2922
                    array(
2923
                        'error' => true,
2924
                        'message' => $lang->get('key_is_not_correct'),
2925
                    ),
2926
                    'encode'
2927
                );
2928
                break;
2929
            }
2930
2931
            $result = listDeletedUsers();
2932
2933
            echo prepareExchangedData(
2934
                array(
2935
                    'error' => false,
2936
                    'result' => $result,
2937
                    'debug' => '',
2938
                ),
2939
                'encode'
2940
            );
2941
            
2942
            break;
2943
        
2944
        case "purge_user":
2945
            // Check KEY
2946
            if ($post_key !== $session->get('key')) {
2947
                echo prepareExchangedData(
2948
                    array(
2949
                        'error' => true,
2950
                        'message' => $lang->get('key_is_not_correct'),
2951
                    ),
2952
                    'encode'
2953
                );
2954
                break;
2955
            }
2956
2957
            // Prepare variables
2958
            $userId = (int) filter_var($dataReceived['user_id'], FILTER_SANITIZE_NUMBER_INT);
2959
        
2960
            if (empty($userId)) {
2961
                echo prepareExchangedData([
2962
                    'error' => true,
2963
                    'message' => $lang->get('error_empty_data'),
2964
                ], 'encode');
2965
                break;
2966
            }
2967
            
2968
            $result = purgeDeletedUserById($userId);
2969
2970
            echo prepareExchangedData(
2971
                $result,
2972
                'encode'
2973
            );
2974
            
2975
            break;
2976
2977
        case 'get_purgeable_users':
2978
            // Check KEY
2979
            if ($post_key !== $session->get('key')) {
2980
                echo prepareExchangedData(
2981
                    array(
2982
                        'error' => true,
2983
                        'message' => $lang->get('key_is_not_correct'),
2984
                    ),
2985
                    'encode'
2986
                );
2987
                break;
2988
            }
2989
2990
            // Check if user is admin
2991
            if ($session->get('user-admin') !== 1 && $session->get('user-can_manage_all_users') !== 1) {
2992
                echo prepareExchangedData(
2993
                    [
2994
                        'error' => true,
2995
                        'message' => $lang->get('error_not_allowed'),
2996
                    ],
2997
                    'encode'
2998
                );
2999
                break;
3000
            }
3001
3002
            // Prepare variables
3003
            $daysRetention = filter_var($dataReceived['days_retention'], FILTER_SANITIZE_NUMBER_INT);
3004
            $daysRetention = empty($daysRetention) ? 90 : (int)$daysRetention;
3005
            $cutoffTimestamp = time() - ($daysRetention * 86400);
3006
            
3007
            try {
3008
                // Get list of users to delete
3009
                $users = DB::query(
3010
                    "SELECT id FROM " . prefixTable("users") . " 
3011
                    WHERE deleted_at IS NOT NULL 
3012
                    AND deleted_at > 0
3013
                    AND deleted_at < %i
3014
                    ORDER BY deleted_at ASC",
3015
                    $cutoffTimestamp
3016
                );
3017
                
3018
                $userIds = array_column($users, 'id');
3019
                
3020
                echo prepareExchangedData(
3021
                    [
3022
                        'error' => false,
3023
                        'user_ids' => $userIds,
3024
                        'count' => count($userIds),
3025
                        'retention_days' => $daysRetention
3026
                    ],
3027
                    'encode'
3028
                );
3029
                
3030
            } catch (Exception $e) {
3031
                echo prepareExchangedData(
3032
                    [
3033
                        'error' => true,
3034
                        'message' => $lang->get('error') . ': ' . $e->getMessage(),
3035
                    ],
3036
                    'encode'
3037
                );
3038
            }
3039
            
3040
            break;
3041
3042
        case 'purge_users_batch':            
3043
            // Check KEY
3044
            if ($post_key !== $session->get('key')) {
3045
                echo prepareExchangedData(
3046
                    array(
3047
                        'error' => true,
3048
                        'message' => $lang->get('key_is_not_correct'),
3049
                    ),
3050
                    'encode'
3051
                );
3052
                break;
3053
            }
3054
3055
            // Check if user is admin
3056
            if ($session->get('user-admin') !== 1 && $session->get('user-can_manage_all_users') !== 1) {
3057
                echo prepareExchangedData(
3058
                    [
3059
                        'error' => true,
3060
                        'message' => $lang->get('error_not_allowed'),
3061
                    ],
3062
                    'encode'
3063
                );
3064
                break;
3065
            }
3066
3067
            // Prepare variables
3068
            $daysRetention = filter_var($dataReceived['days_retention'], FILTER_SANITIZE_NUMBER_INT);
3069
            $userIds = filter_var_array(
3070
                $dataReceived['user_ids'],
3071
                FILTER_SANITIZE_NUMBER_INT
3072
            );
3073
            
3074
            // Ensure user id has been provided
3075
            if (empty($userIds) || !is_array($userIds)) {
3076
                echo prepareExchangedData(
3077
                    [
3078
                        'error' => true,
3079
                        'message' => $lang->get('error_empty_data'),
3080
                    ],
3081
                    'encode'
3082
                );
3083
                break;
3084
            }
3085
            
3086
            $purgedCount = 0;
3087
            $errors = [];
3088
            $cutoffTimestamp = time() - ((int)$daysRetention * 86400);        
3089
                        
3090
            foreach ($userIds as $userId) {
3091
                $userId = (int)$userId;
3092
                
3093
                try {
3094
                    $result = purgeDeletedUserById($userId);
3095
                    $purgedCount++;
3096
                    
3097
                } catch (Exception $e) {
3098
                    DB::rollback();
3099
                    $errors[] = "User ID $userId: " . $e->getMessage();
3100
                }
3101
            }
3102
            
3103
            echo prepareExchangedData(
3104
                [
3105
                    'error' => false,
3106
                    'purged_count' => $purgedCount,
3107
                    'total_in_batch' => count($userIds),
3108
                    'errors' => $errors,
3109
                    'message' => $purgedCount . ' user(s) purged in this batch'
3110
                ],
3111
                'encode'
3112
            );
3113
            
3114
            break;
3115
3116
        case 'restore_user':
3117
            // Check KEY
3118
            if ($post_key !== $session->get('key')) {
3119
                echo prepareExchangedData(
3120
                    array(
3121
                        'error' => true,
3122
                        'message' => $lang->get('key_is_not_correct'),
3123
                    ),
3124
                    'encode'
3125
                );
3126
                break;
3127
            }
3128
3129
            // Check if user is admin
3130
            if ($session->get('user-admin') !== 1) {
3131
                echo prepareExchangedData(
3132
                    array('error' => true, 'message' => 'Insufficient rights'),
3133
                    'encode'
3134
                );
3135
                break;
3136
            }
3137
3138
            // Prepare variables
3139
            $userId = filter_var($dataReceived['user_id'], FILTER_SANITIZE_NUMBER_INT);
3140
            
3141
            // Get info about user
3142
            $data_user = DB::queryFirstRow(
3143
                'SELECT login FROM ' . prefixTable('users') . ' WHERE id = %i',
3144
                $userId
3145
            );
3146
            
3147
            if ($data_user === null) {
3148
                echo prepareExchangedData(
3149
                    array('error' => true, 'message' => 'User not found'),
3150
                    'encode'
3151
                );
3152
                break;
3153
            }
3154
            
3155
            // Remove user suffix "_deleted_timestamp"
3156
            $deletedSuffix = '_deleted_' . substr($data_user['login'], strrpos($data_user['login'], '_deleted_') + 9);
3157
            $originalLogin = str_replace($deletedSuffix, '', $data_user['login']);
3158
            
3159
            // Restore user
3160
            DB::update(
3161
                prefixTable('users'),
3162
                array(
3163
                    'login' => $originalLogin,
3164
                    'deleted_at' => null,
3165
                    'disabled' => 0,
3166
                ),
3167
                'id = %i',
3168
                $userId
3169
            );
3170
            
3171
            echo prepareExchangedData(
3172
                array('error' => false, 'message' => 'User restored successfully'),
3173
                'encode'
3174
            );
3175
            break;
3176
    }
3177
    // # NEW LOGIN FOR USER HAS BEEN DEFINED ##
3178
} elseif (!empty(filter_input(INPUT_POST, 'newValue', FILTER_SANITIZE_FULL_SPECIAL_CHARS))) {
3179
    // Prepare POST variables
3180
    $value = explode('_', filter_input(INPUT_POST, 'id', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
3181
    $post_newValue = filter_input(INPUT_POST, 'newValue', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
3182
3183
    // Get info about user
3184
    $data_user = DB::queryFirstRow(
3185
        'SELECT admin, isAdministratedByRole FROM ' . prefixTable('users') . '
3186
        WHERE id = %i',
3187
        $value[1]
3188
    );
3189
3190
    // Is this user allowed to do this?
3191
    if (
3192
        (int) $session->get('user-admin') === 1
3193
        || (in_array($data_user['isAdministratedByRole'], $session->get('user-roles_array')))
3194
        || ((int) $session->get('user-can_manage_all_users') === 1 && (int) $data_user['admin'] !== 1)
3195
        || ($session->get('user-id') === $value[1])
3196
    ) {
3197
        if ($value[0] === 'userlanguage') {
3198
            $value[0] = 'user_language';
3199
            $post_newValue = strtolower($post_newValue);
3200
        }
3201
        
3202
        // Check that operation is allowed
3203
        if (in_array(
3204
            $value[0],
3205
            array('login', 'pw', 'email', 'treeloadstrategy', 'usertimezone', 'yubico_user_key', 'yubico_user_id', 'agses-usercardid', 'user_language', 'psk', 'split_view_mode', 'show_subfolders')
3206
        )) {
3207
            DB::update(
3208
                prefixTable('users'),
3209
                array(
3210
                    $value[0] => $post_newValue,
3211
                ),
3212
                'id = %i',
3213
                $value[1]
3214
            );
3215
            // update LOG
3216
            logEvents(
3217
                $SETTINGS,
3218
                'user_mngt',
3219
                'at_user_new_' . $value[0] . ':' . $value[1],
3220
                (string) $session->get('user-id'),
3221
                $session->get('user-login'),
3222
                filter_input(INPUT_POST, 'id', FILTER_SANITIZE_FULL_SPECIAL_CHARS)
3223
            );
3224
3225
            // refresh SESSION if requested
3226
            // Session keys mapping
3227
            $sessionMapping = [
3228
                'treeloadstrategy' => 'user-tree_load_strategy',
3229
                'usertimezone' => 'user-timezone',
3230
                'userlanguage' => 'user-language',
3231
                'agses-usercardid' => null, 
3232
                'email' => 'user-email',
3233
                'split_view_mode' => 'user-split_view_mode',
3234
                'show_subfolders' => 'user-show_subfolders',
3235
            ];
3236
            // Update session
3237
            if (array_key_exists($value[0], $sessionMapping)) {
3238
                $sessionKey = $sessionMapping[$value[0]];
3239
                if ($sessionKey !== null) {
3240
                    $session->set($sessionKey, $post_newValue);
3241
                }
3242
            }
3243
            
3244
            // Display info
3245
            echo htmlentities($post_newValue, ENT_QUOTES);
3246
        }
3247
    }
3248
    // # ADMIN FOR USER HAS BEEN DEFINED ##
3249
} elseif (null !== filter_input(INPUT_POST, 'newadmin', FILTER_SANITIZE_NUMBER_INT)) {
3250
    $id = explode('_', filter_input(INPUT_POST, 'id', FILTER_SANITIZE_FULL_SPECIAL_CHARS));
3251
3252
    // Get info about user
3253
    $data_user = DB::queryFirstRow(
3254
        'SELECT admin, isAdministratedByRole FROM ' . prefixTable('users') . '
3255
        WHERE id = %i',
3256
        $id[1]
3257
    );
3258
3259
    // Is this user allowed to do this?
3260
    if (
3261
        (int) $session->get('user-admin') === 1
3262
        || (in_array($data_user['isAdministratedByRole'], $session->get('user-roles_array')))
3263
        || ((int) $session->get('user-can_manage_all_users') === 1 && (int) $data_user['admin'] !== 1)
3264
        || ($session->get('user-id') === $id[1])
3265
    ) {
3266
        DB::update(
3267
            prefixTable('users'),
3268
            array(
3269
                'admin' => filter_input(INPUT_POST, 'newadmin', FILTER_SANITIZE_NUMBER_INT),
3270
            ),
3271
            'id = %i',
3272
            $id[1]
3273
        );
3274
        // Display info
3275
        if (filter_input(INPUT_POST, 'newadmin', FILTER_SANITIZE_NUMBER_INT) === 1) {
3276
            echo 'Oui';
3277
        } else {
3278
            echo 'Non';
3279
        }
3280
    }
3281
}
3282
3283
/**
3284
 * List deleted users
3285
 * 
3286
 * @return array
3287
 */
3288
function listDeletedUsers(): array
3289
{
3290
    $users = DB::query(
3291
        "SELECT id, login, email, deleted_at, 
3292
                DATEDIFF(NOW(), FROM_UNIXTIME(deleted_at)) as days_since_deletion
3293
         FROM " . prefixTable("users") . " 
3294
         WHERE deleted_at IS NOT NULL 
3295
         AND deleted_at > 0
3296
         ORDER BY deleted_at DESC"
3297
    );
3298
    
3299
    return [
3300
        'error' => false,
3301
        'users' => $users,
3302
        'count' => count($users)
3303
    ];
3304
}
3305
3306
/**
3307
 * Purge deleted user by ID
3308
 * 
3309
 * @param int $userId
3310
 * @return array
3311
 */
3312
function purgeDeletedUserById($userId): array
3313
{
3314
    $session = SessionManager::getSession();
3315
    $lang = new Language($session->get('user-language') ?? 'english');
3316
    
3317
    // Vérifier que l'utilisateur est bien marqué deleted
3318
    $user = DB::queryFirstRow(
3319
        "SELECT id, login, deleted_at FROM " . prefixTable("users") . " 
3320
         WHERE id = %i 
3321
         AND deleted_at IS NOT NULL 
3322
         AND deleted_at > 0",
3323
        $userId
3324
    );
3325
    
3326
    if (!$user) {
3327
        return [
3328
            'error' => true,
3329
            'message' => 'User not found or not deleted'
3330
        ];
3331
    }
3332
3333
    DB::startTransaction();
3334
    
3335
    try {
3336
        // Delete private keys
3337
        DB::delete(
3338
            prefixTable('user_private_keys'),
3339
            'user_id = %i',
3340
            $userId
3341
        );       
3342
3343
        // delete user api
3344
        DB::delete(
3345
            prefixTable('api'),
3346
            'user_id = %i',
3347
            $userId
3348
        );
3349
        
3350
        // Delete cache
3351
        DB::delete(
3352
            prefixTable('cache'),
3353
            'author = %i',
3354
            $userId
3355
        );
3356
3357
        // delete personal folder and subfolders
3358
        $data = DB::queryFirstRow(
3359
            'SELECT id FROM ' . prefixTable('nested_tree') . '
3360
            WHERE title = %s AND personal_folder = %i',
3361
            $userId,
3362
            '1'
3363
        );
3364
3365
        // Delete tokens
3366
        DB::delete(
3367
            prefixTable('tokens'),
3368
            'user_id = %i',
3369
            $userId
3370
        );
3371
3372
        // Get through each subfolder
3373
        if (!empty($data['id'])) {
3374
            $tree = new NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
3375
            $folders = $tree->getDescendants($data['id'], true);
3376
            foreach ($folders as $folder) {
3377
                // delete folder
3378
                DB::delete(prefixTable('nested_tree'), 'id = %i AND personal_folder = %i', $folder->id, '1');
3379
                // delete items & logs
3380
                $items = DB::query(
3381
                    'SELECT id FROM ' . prefixTable('items') . '
3382
                    WHERE id_tree=%i AND perso = %i',
3383
                    $folder->id,
3384
                    '1'
3385
                );
3386
                foreach ($items as $item) {
3387
                    // Delete item
3388
                    DB::delete(prefixTable('items'), 'id = %i', $item['id']);
3389
                    // log
3390
                    DB::delete(prefixTable('log_items'), 'id_item = %i', $item['id']);
3391
                }
3392
            }
3393
            // rebuild tree
3394
            $tree = new NestedTree(prefixTable('nested_tree'), 'id', 'parent_id', 'title');
3395
            $tree->rebuild();
3396
        }
3397
3398
        // Delete objects keys
3399
        deleteUserObjetsKeys((int) $userId);
3400
        
3401
        // Delete user
3402
        DB::delete(
3403
            prefixTable('users'),
3404
            'id = %i',
3405
            $userId
3406
        );   
3407
3408
        // Delete any process related to user
3409
        $processes = DB::query(
3410
            'SELECT increment_id
3411
            FROM ' . prefixTable('background_tasks') . '
3412
            WHERE JSON_EXTRACT(arguments, "$.new_user_id") = %i',
3413
            $userId
3414
        );
3415
        $process_id = -1;
3416
        foreach ($processes as $process) {
3417
            // Delete task
3418
            DB::delete(
3419
                prefixTable('background_subtasks'),
3420
                'task_id = %i',
3421
                $process['increment_id']
3422
            );
3423
            $process_id = $process['increment_id'];
3424
        }
3425
        // Delete main process
3426
        if ($process_id > -1) {
3427
            DB::delete(
3428
                prefixTable('background_tasks'),
3429
                'increment_id = %i',
3430
                $process_id
3431
            );
3432
        }
3433
        
3434
        // Log de la purge
3435
        logEvents(
3436
            $GLOBALS['SETTINGS'],
3437
            'user_mngt',
3438
            'user_purged',
3439
            (string) $session->get('user-id'),
3440
            $session->get('login'),
3441
            $userId
3442
        );
3443
        
3444
        DB::commit();
3445
        
3446
        return [
3447
            'error' => false,
3448
            'message' => $lang->get('user_purged_successfully')
3449
        ];
3450
        
3451
    } catch (Exception $e) {
3452
        DB::rollback();
3453
        return [
3454
            'error' => true,
3455
            'message' => $e->getMessage()
3456
        ];
3457
    }
3458
}
3459
3460
/**
3461
 * Purge old deleted users
3462
 * 
3463
 * @param int $daysRetention
3464
 * @return array
3465
 *//*
3466
function purgeOldDeletedUsers($daysRetention = 90): array
3467
{
3468
    $session = SessionManager::getSession();
3469
    $lang = new Language($session->get('user-language') ?? 'english');
3470
3471
    $cutoffTimestamp = time() - ($daysRetention * 86400);
3472
    
3473
    // Récupérer les utilisateurs à purger
3474
    $usersToDelete = DB::query(
3475
        "SELECT id, login FROM " . prefixTable("users") . " 
3476
         WHERE deleted_at IS NOT NULL 
3477
         AND deleted_at > 0
3478
         AND deleted_at < %i",
3479
        $cutoffTimestamp
3480
    );
3481
    
3482
    $purgedCount = 0;
3483
    $errors = [];
3484
    
3485
    foreach ($usersToDelete as $user) {
3486
        $result = purgeDeletedUserById($user['id']);
3487
        
3488
        if ($result['error']) {
3489
            $errors[] = $user['login'] . ': ' . $result['message'];
3490
        } else {
3491
            $purgedCount++;
3492
        }
3493
    }
3494
    
3495
    return [
3496
        'error' => count($errors) > 0,
3497
        'purged_count' => $purgedCount,
3498
        'total_found' => count($usersToDelete),
3499
        'errors' => $errors,
3500
        'message' => $purgedCount . ' ' . $lang->get('users_purged_successfully')
3501
    ];
3502
}*/
3503
3504
/**
3505
 * Return the level of access on a folder.
3506
 *
3507
 * @param string $new_val      New value
3508
 * @param string $existing_val Current value
3509
 *
3510
 * @return string Returned index
3511
 */
3512
function evaluateFolderAccesLevel($new_val, $existing_val)
3513
{
3514
    $levels = array(
3515
        'W' => 30,
3516
        'ND' => 20,
3517
        'NE' => 15,
3518
        'NDNE' => 10,
3519
        'R' => 10,
3520
    );
3521
3522
    $current_level_points = empty($existing_val) === true ? 0 : $levels[$existing_val];
3523
    $new_level_points = empty($new_val) === true ? 0 : $levels[$new_val];
3524
3525
    // check if new is > to current one (always keep the highest level)
3526
    if (($new_val === 'ND' && $existing_val === 'NE')
3527
        || ($new_val === 'NE' && $existing_val === 'ND')
3528
    ) {
3529
        return 'NDNE';
3530
    } else {
3531
        if ($current_level_points > $new_level_points) {
3532
            return $existing_val;
3533
        } else {
3534
            return $new_val;
3535
        }
3536
    }
3537
}
3538