nilsteampassnet /
TeamPass
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
| 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 admin.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 TeampassClasses\SessionManager\SessionManager; |
||
| 33 | use Symfony\Component\HttpFoundation\Request as SymfonyRequest; |
||
| 34 | use TeampassClasses\Language\Language; |
||
| 35 | use TeampassClasses\PerformChecks\PerformChecks; |
||
| 36 | use TeampassClasses\ConfigManager\ConfigManager; |
||
| 37 | |||
| 38 | // Load functions |
||
| 39 | require_once __DIR__.'/../sources/main.functions.php'; |
||
| 40 | |||
| 41 | // init |
||
| 42 | loadClasses('DB'); |
||
| 43 | $session = SessionManager::getSession(); |
||
| 44 | $request = SymfonyRequest::createFromGlobals(); |
||
| 45 | $lang = new Language($session->get('user-language') ?? 'english'); |
||
| 46 | |||
| 47 | // Load config |
||
| 48 | $configManager = new ConfigManager(); |
||
| 49 | $SETTINGS = $configManager->getAllSettings(); |
||
| 50 | |||
| 51 | // Do checks |
||
| 52 | $checkUserAccess = new PerformChecks( |
||
| 53 | dataSanitizer( |
||
| 54 | [ |
||
| 55 | 'type' => htmlspecialchars($request->request->get('type', ''), ENT_QUOTES, 'UTF-8'), |
||
| 56 | ], |
||
| 57 | [ |
||
| 58 | 'type' => 'trim|escape', |
||
| 59 | ], |
||
| 60 | ), |
||
| 61 | [ |
||
| 62 | 'user_id' => returnIfSet($session->get('user-id'), null), |
||
| 63 | 'user_key' => returnIfSet($session->get('key'), null), |
||
| 64 | ] |
||
| 65 | ); |
||
| 66 | |||
| 67 | // Handle the case |
||
| 68 | echo $checkUserAccess->caseHandler(); |
||
| 69 | if ($checkUserAccess->checkSession() === false || $checkUserAccess->userAccessPage('admin') === false) { |
||
| 70 | // Not allowed page |
||
| 71 | $session->set('system-error_code', ERR_NOT_ALLOWED); |
||
| 72 | include $SETTINGS['cpassman_dir'] . '/error.php'; |
||
| 73 | exit; |
||
| 74 | } |
||
| 75 | |||
| 76 | // Define Timezone |
||
| 77 | date_default_timezone_set($SETTINGS['timezone'] ?? 'UTC'); |
||
| 78 | |||
| 79 | // Set header properties |
||
| 80 | header('Content-type: text/html; charset=utf-8'); |
||
| 81 | header('Cache-Control: no-cache, no-store, must-revalidate'); |
||
| 82 | |||
| 83 | ?> |
||
| 84 | |||
| 85 | <!-- Content Header (Page header) --> |
||
| 86 | <div class="content-header"> |
||
| 87 | <div class="container-fluid"> |
||
| 88 | <div class="row mb-2"> |
||
| 89 | <div class="col-sm-6"> |
||
| 90 | <h1 class="m-0 text-dark"> |
||
| 91 | <i class="fas fa-tachometer-alt"></i> <?php echo $lang->get('dashboard'); ?> |
||
| 92 | </h1> |
||
| 93 | </div> |
||
| 94 | <div class="col-sm-6"> |
||
| 95 | <ol class="breadcrumb float-sm-right"> |
||
| 96 | <li class="breadcrumb-item"><a href="index.php?page=items"><?php echo $lang->get('home'); ?></a></li> |
||
| 97 | <li class="breadcrumb-item active"><?php echo $lang->get('admin'); ?></li> |
||
| 98 | </ol> |
||
| 99 | </div> |
||
| 100 | </div> |
||
| 101 | </div> |
||
| 102 | </div> |
||
| 103 | |||
| 104 | <!-- Main content --> |
||
| 105 | <section class="content"> |
||
| 106 | <div class="container-fluid"> |
||
| 107 | |||
| 108 | <!-- Info Box for last update and GitHub link --> |
||
| 109 | <div class="row mb-3"> |
||
| 110 | <div class="col-12"> |
||
| 111 | <div class="alert alert-info alert-dismissible"> |
||
| 112 | <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button> |
||
| 113 | <h5> |
||
| 114 | <i class="icon fas fa-info"></i> <?php echo $lang->get('admin_info_header'); ?> |
||
| 115 | </h5> |
||
| 116 | <span> |
||
| 117 | <i class="fa-regular fa-eye mr-2"></i><?php echo $lang->get('currently_using_version')." <b>".TP_VERSION.".<i>".TP_VERSION_MINOR."</i></b>"; ?> |
||
| 118 | </span> | |
||
| 119 | <span id="admin-last-refresh"><?php echo $lang->get('admin_last_refresh'); ?>: <span class="badge badge-light" id="last-refresh-time">--:--:--</span></span> |
||
| 120 | | |
||
| 121 | <span class="ml-3"> |
||
| 122 | <a href="https://github.com/nilsteampassnet/TeamPass/releases" target="_blank" class="text-white"> |
||
| 123 | <i class="fab fa-github"></i> <?php echo $lang->get('admin_view_changelog_github'); ?> |
||
| 124 | </a> |
||
| 125 | </span> |
||
| 126 | </div> |
||
| 127 | </div> |
||
| 128 | </div> |
||
| 129 | |||
| 130 | <!-- Main tabs card --> |
||
| 131 | <div class="card card-primary card-outline card-outline-tabs"> |
||
| 132 | <div class="card-body"> |
||
| 133 | <div class="tab-content" id="admin-tabs-content"> |
||
| 134 | |||
| 135 | <!-- ============================================ --> |
||
| 136 | <!-- DASHBOARD TAB --> |
||
| 137 | <!-- ============================================ --> |
||
| 138 | <div class="tab-pane fade show active" id="tab-dashboard" role="tabpanel" aria-labelledby="tab-dashboard-link"> |
||
| 139 | |||
| 140 | <!-- Statistics Cards Row --> |
||
| 141 | <div class="row"> |
||
| 142 | <!-- Users Statistics --> |
||
| 143 | <div class="col-lg-3 col-6"> |
||
| 144 | <div class="small-box bg-info"> |
||
| 145 | <div class="inner"> |
||
| 146 | <h3 id="stat-users-active">-</h3> |
||
| 147 | <p><?php echo $lang->get('active_users'); ?></p> |
||
| 148 | <div class="small text-white"> |
||
| 149 | <span><?php echo $lang->get('online'); ?>: <strong id="stat-users-online">-</strong></span><br> |
||
| 150 | <span><?php echo $lang->get('blocked'); ?>: <strong id="stat-users-blocked">-</strong></span> |
||
| 151 | </div> |
||
| 152 | </div> |
||
| 153 | <div class="icon"> |
||
| 154 | <i class="fas fa-users"></i> |
||
| 155 | </div> |
||
| 156 | <a href="index.php?page=users" class="small-box-footer"> |
||
| 157 | <?php echo $lang->get('open'); ?> <i class="fas fa-arrow-circle-right"></i> |
||
| 158 | </a> |
||
| 159 | <div class="overlay" id="loading-stat-users" style="display:none;"> |
||
| 160 | <i class="fas fa-sync fa-spin"></i> |
||
| 161 | </div> |
||
| 162 | </div> |
||
| 163 | </div> |
||
| 164 | |||
| 165 | <!-- Items Statistics --> |
||
| 166 | <div class="col-lg-3 col-6"> |
||
| 167 | <div class="small-box bg-success"> |
||
| 168 | <div class="inner"> |
||
| 169 | <h3 id="stat-items-total">-</h3> |
||
| 170 | <p><?php echo $lang->get('total_items'); ?></p> |
||
| 171 | <div class="small text-white"> |
||
| 172 | <span><?php echo $lang->get('shared'); ?>: <strong id="stat-items-shared">-</strong></span><br> |
||
| 173 | <span><?php echo $lang->get('personal'); ?>: <strong id="stat-items-personal">-</strong></span> |
||
| 174 | </div> |
||
| 175 | </div> |
||
| 176 | <div class="icon"> |
||
| 177 | <i class="fas fa-key"></i> |
||
| 178 | </div> |
||
| 179 | <a href="index.php?page=utilities.deletion" class="small-box-footer"> |
||
| 180 | <?php echo $lang->get('open'); ?> <i class="fas fa-arrow-circle-right"></i> |
||
| 181 | </a> |
||
| 182 | <div class="overlay" id="loading-stat-items" style="display:none;"> |
||
| 183 | <i class="fas fa-sync fa-spin"></i> |
||
| 184 | </div> |
||
| 185 | </div> |
||
| 186 | </div> |
||
| 187 | |||
| 188 | <!-- Folders Statistics --> |
||
| 189 | <div class="col-lg-3 col-6"> |
||
| 190 | <div class="small-box bg-warning"> |
||
| 191 | <div class="inner"> |
||
| 192 | <h3 id="stat-folders-total">-</h3> |
||
| 193 | <p><?php echo $lang->get('total_folders'); ?></p> |
||
| 194 | <div class="small text-white"> |
||
| 195 | <span><?php echo $lang->get('public'); ?>: <strong id="stat-folders-public">-</strong></span><br> |
||
| 196 | <span><?php echo $lang->get('personal'); ?>: <strong id="stat-folders-personal">-</strong></span> |
||
| 197 | </div> |
||
| 198 | </div> |
||
| 199 | <div class="icon"> |
||
| 200 | <i class="fas fa-folder-open"></i> |
||
| 201 | </div> |
||
| 202 | <a href="index.php?page=folders" class="small-box-footer"> |
||
| 203 | <?php echo $lang->get('open'); ?> <i class="fas fa-arrow-circle-right"></i> |
||
| 204 | </a> |
||
| 205 | <div class="overlay" id="loading-stat-folders" style="display:none;"> |
||
| 206 | <i class="fas fa-sync fa-spin"></i> |
||
| 207 | </div> |
||
| 208 | </div> |
||
| 209 | </div> |
||
| 210 | |||
| 211 | <!-- Logs Statistics --> |
||
| 212 | <div class="col-lg-3 col-6"> |
||
| 213 | <div class="small-box bg-danger"> |
||
| 214 | <div class="inner"> |
||
| 215 | <h3 id="stat-logs-actions">-</h3> |
||
| 216 | <p><?php echo $lang->get('logs_24h'); ?></p> |
||
| 217 | <div class="small text-white"> |
||
| 218 | <span><?php echo $lang->get('accesses'); ?>: <strong id="stat-logs-accesses">-</strong></span><br> |
||
| 219 | <span><?php echo $lang->get('errors'); ?>: <strong id="stat-logs-errors">-</strong></span> |
||
| 220 | </div> |
||
| 221 | </div> |
||
| 222 | <div class="icon"> |
||
| 223 | <i class="fas fa-file-alt"></i> |
||
| 224 | </div> |
||
| 225 | <a href="index.php?page=utilities.logs" class="small-box-footer"> |
||
| 226 | <?php echo $lang->get('open'); ?> <i class="fas fa-arrow-circle-right"></i> |
||
| 227 | </a> |
||
| 228 | <div class="overlay" id="loading-stat-logs" style="display:none;"> |
||
| 229 | <i class="fas fa-sync fa-spin"></i> |
||
| 230 | </div> |
||
| 231 | </div> |
||
| 232 | </div> |
||
| 233 | </div> |
||
| 234 | |||
| 235 | <!-- System Health and Teampass Information Row --> |
||
| 236 | <div class="row"> |
||
| 237 | <!-- System Health Card --> |
||
| 238 | <div class="col-lg-5"> |
||
| 239 | <div class="card card-success"> |
||
| 240 | <div class="card-header"> |
||
| 241 | <h3 class="card-title"> |
||
| 242 | <i class="fas fa-heartbeat"></i> |
||
| 243 | <?php echo $lang->get('system_health'); ?> |
||
| 244 | </h3> |
||
| 245 | </div> |
||
| 246 | <div class="card-body"> |
||
| 247 | <ul class="list-group list-group-flush"> |
||
| 248 | <li class="list-group-item d-flex justify-content-between align-items-center"> |
||
| 249 | <span><i class="fas fa-lock text-success"></i> <?php echo $lang->get('health_encryption'); ?></span> |
||
| 250 | <span class="badge badge-success" id="health-encryption">-</span> |
||
| 251 | </li> |
||
| 252 | <!-- |
||
| 253 | <li class="list-group-item d-flex justify-content-between align-items-center"> |
||
| 254 | <span><i class="fas fa-file-code text-success"></i> <?php echo $lang->get('database_integrity'); ?></span> |
||
| 255 | <span class="badge badge-success" id="health-database-integrity">-</span> |
||
| 256 | </li> |
||
| 257 | --> |
||
| 258 | <li class="list-group-item d-flex justify-content-between align-items-center"> |
||
| 259 | <span><i class="fas fa-user-clock text-success"></i> <?php echo $lang->get('health_sessions'); ?></span> |
||
| 260 | <span class="badge badge-info" id="health-sessions">-</span> |
||
| 261 | </li> |
||
| 262 | <li class="list-group-item d-flex justify-content-between align-items-center"> |
||
| 263 | <span><i class="fas fa-history text-success"></i> <?php echo $lang->get('health_cron'); ?></span> |
||
| 264 | <span class="badge badge-success" id="health-cron">-</span> |
||
| 265 | </li> |
||
| 266 | <li class="list-group-item d-flex justify-content-between align-items-center"> |
||
| 267 | <span><i class="fas fa-file-code text-warning"></i> <?php echo $lang->get('health_unknown_files'); ?></span> |
||
| 268 | <span class="badge badge-warning" id="health-unknown-files">-</span> |
||
| 269 | </li> |
||
| 270 | </ul> |
||
| 271 | </div> |
||
| 272 | <div class="overlay" id="loading-health" style="display:none;"> |
||
| 273 | <i class="fas fa-sync fa-spin"></i> |
||
| 274 | </div> |
||
| 275 | </div> |
||
| 276 | </div> |
||
| 277 | |||
| 278 | <!-- Teampass Information Card --> |
||
| 279 | <div class="col-lg-7"> |
||
| 280 | <div class="card card-default"> |
||
| 281 | <div class="card-header"> |
||
| 282 | <h3 class="card-title"> |
||
| 283 | <i class="fa-solid fa-barcode"></i> |
||
| 284 | <?php echo $lang->get('teampass_information'); ?> |
||
| 285 | </h3> |
||
| 286 | </div> |
||
| 287 | <div class="card-body"> |
||
| 288 | <ul class="list-group list-group-flush"> |
||
| 289 | <?php |
||
| 290 | if (isset($SETTINGS['enable_tasks_manager']) === true && (int) $SETTINGS['enable_tasks_manager'] === 0) { |
||
| 291 | echo '<div class="alert bg-orange disabled" role="alert"> |
||
| 292 | <h5><i class="fa-solid fa-exclamation-triangle mr-2"></i>Since 3.0.0.23, TASKS manager is enabled by default and is mandatory.</h5> |
||
| 293 | <p>Please ensure that cron job is set and enabled.<br />Open Tasks page and check status.</p> |
||
| 294 | <p><a href="https://documentation.teampass.net/#/manage/tasks" target="_blank"><i class="fa-solid fa-book mr-2"></i>Check documentation</a>.</p> |
||
| 295 | </div>'; |
||
| 296 | } else { |
||
| 297 | ?> |
||
| 298 | <div class=""> |
||
| 299 | <?php |
||
| 300 | |||
| 301 | ?> |
||
| 302 | </div> |
||
| 303 | <?php |
||
| 304 | } |
||
| 305 | ?> |
||
| 306 | |||
| 307 | |||
| 308 | <li class="list-group-item d-flex justify-content-between align-items-center"> |
||
| 309 | <span><i class="fa-solid fa-file-shield text-info"></i> <?php echo $lang->get('perform_file_integrity_check'); ?></span> |
||
| 310 | <span> |
||
| 311 | <button type="button" class="btn btn-primary btn-sm ml-2" id="check-project-files-btn" onclick="performProjectFilesIntegrityCheck()"> |
||
| 312 | <i class="fas fa-caret-right"></i> |
||
| 313 | </button> |
||
| 314 | </span> |
||
| 315 | </li> |
||
| 316 | <?php |
||
| 317 | |||
| 318 | // Has the transparent recovery migration been done? |
||
| 319 | DB::query( |
||
| 320 | "SELECT id FROM " . prefixTable('users') . " |
||
| 321 | WHERE (user_derivation_seed IS NULL |
||
| 322 | OR private_key_backup IS NULL) |
||
| 323 | AND disabled = 0" |
||
| 324 | ); |
||
| 325 | if (DB::count() !== 0) { |
||
| 326 | ?> |
||
| 327 | <li class="list-group-item d-flex justify-content-between align-items-center"> |
||
| 328 | <span><i class="fa-solid fa-chart-bar text-info"></i> <?php echo $lang->get('perform_transparent_recovery_check'); ?></span> |
||
| 329 | <span> |
||
| 330 | <button type="button" class="btn btn-primary btn-sm ml-2" id="check-transparent-recovery-btn" onclick="performTransparentRecoveryCheck()"> |
||
| 331 | <i class="fas fa-caret-right"></i> |
||
| 332 | </button> |
||
| 333 | </span> |
||
| 334 | </li> |
||
| 335 | <?php |
||
| 336 | } |
||
| 337 | |||
| 338 | // Has the personal items migration been done for users? |
||
| 339 | $stats = DB::query( |
||
| 340 | "SELECT |
||
| 341 | COUNT(*) as total_users, |
||
| 342 | SUM(CASE WHEN personal_items_migrated = 1 THEN 1 ELSE 0 END) as migrated_users, |
||
| 343 | SUM(CASE WHEN personal_items_migrated = 0 THEN 1 ELSE 0 END) as pending_users |
||
| 344 | FROM " . prefixTable('users') . " |
||
| 345 | WHERE disabled = 0 AND deleted_at IS NULL" |
||
| 346 | ); |
||
| 347 | $progressPercent = ($stats[0]['migrated_users'] / $stats[0]['total_users']) * 100; |
||
| 348 | if ($progressPercent !== 100) { |
||
| 349 | ?> |
||
| 350 | <li class="list-group-item d-flex justify-content-between align-items-center"> |
||
| 351 | <span><i class="fa-solid fa-chart-bar text-info"></i> <?php echo $lang->get('get_personal_items_migration_status'); ?></span> |
||
| 352 | <span> |
||
| 353 | <button type="button" class="btn btn-primary btn-sm ml-2" id="personal-items-migration-btn" onclick="performPersonalItemsMigrationCheck()"> |
||
| 354 | <i class="fas fa-caret-right"></i> |
||
| 355 | </button> |
||
| 356 | </span> |
||
| 357 | </li> |
||
| 358 | <?php |
||
| 359 | } |
||
| 360 | // Status on users passwords migration to new encryption Symfony Password |
||
| 361 | $excluded_ids = array(9999991, 9999997, 9999998, 9999999); |
||
| 362 | $user_results = DB::query( |
||
| 363 | "SELECT login |
||
| 364 | FROM ".prefixTable('users')." |
||
| 365 | WHERE pw LIKE %s |
||
| 366 | AND pw NOT LIKE %s |
||
| 367 | AND id NOT IN %ls |
||
| 368 | AND (login NOT LIKE %s OR deleted_at IS NULL)", |
||
| 369 | '$2y$10$%', |
||
| 370 | '$2y$13$%', |
||
| 371 | $excluded_ids, |
||
| 372 | '%_deleted_%' |
||
| 373 | ); |
||
| 374 | if (DB::count() > 0) { |
||
| 375 | $logins_array = array_column($user_results, 'login'); |
||
| 376 | $logins_list = implode(', ', $logins_array); |
||
| 377 | ?> |
||
| 378 | <li class="list-group-item d-flex justify-content-between align-items-center"> |
||
| 379 | <span><i class="fa-solid fa-hand text-warning"></i> |
||
| 380 | Password Encryption Migration Required <span class="badge badge-warning"><?php echo DB::count();?> remaing users</span> |
||
| 381 | </span> |
||
| 382 | <span> |
||
| 383 | <i class="fa-solid fa-info-circle text-primary open-info" data-info="<?php echo DB::count();?> user accounts still use the legacy encryption library and must be migrated before upgrading to version 3.2.0.<br> |
||
| 384 | To migrate: Users must either log in once or have their password updated via the Users management page.<p class='mt-2'>List of remaining users: <?php echo $logins_list;?></p>" data-size="lg" data-title="Importante notice"></i> |
||
| 385 | </span> |
||
| 386 | </li> |
||
| 387 | <?php |
||
| 388 | } |
||
| 389 | |||
| 390 | // Check if tp.config.php file is still present |
||
| 391 | if (file_exists(__DIR__.'/../includes/config/tp.config.php') === true) { |
||
| 392 | echo '<div class="mt-3 alert alert-warning" role="alert"><i class="fa-solid fa-circle-exclamation mr-2"></i>File tp.config.php requires to be deleted. Please do it and refresh this page. This warning shall not be visible anymore.</div>'; |
||
| 393 | } |
||
| 394 | ?> |
||
| 395 | </ul> |
||
| 396 | </div> |
||
| 397 | </div> |
||
| 398 | </div> |
||
| 399 | </div> |
||
| 400 | |||
| 401 | <!-- Live Activity and System Status Row --> |
||
| 402 | <div class="row"> |
||
| 403 | <!-- Live Activity Card --> |
||
| 404 | <div class="col-lg-6"> |
||
| 405 | <div class="card card-warning"> |
||
| 406 | <div class="card-header"> |
||
| 407 | <h3 class="card-title"> |
||
| 408 | <i class="fas fa-circle text-danger blink"></i> |
||
| 409 | <?php echo $lang->get('live_activity'); ?> |
||
| 410 | </h3> |
||
| 411 | <div class="card-tools"> |
||
| 412 | <span class="badge badge-warning" id="activity-refresh-countdown">10s</span> |
||
| 413 | </div> |
||
| 414 | </div> |
||
| 415 | <div class="card-body p-0" style="max-height: 350px; overflow-y: auto;"> |
||
| 416 | <ul class="list-group list-group-flush" id="live-activity-list"> |
||
| 417 | <li class="list-group-item text-center text-muted"> |
||
| 418 | <i class="fas fa-sync fa-spin"></i> <?php echo $lang->get('loading'); ?> |
||
| 419 | </li> |
||
| 420 | </ul> |
||
| 421 | </div> |
||
| 422 | <div class="card-footer clearfix"> |
||
| 423 | <a href="index.php?page=utilities.logs#items" class="btn btn-sm btn-warning float-right"> |
||
| 424 | <?php echo $lang->get('view_all_logs'); ?> |
||
| 425 | </a> |
||
| 426 | </div> |
||
| 427 | <div class="overlay" id="loading-activity" style="display:none;"> |
||
| 428 | <i class="fas fa-sync fa-spin"></i> |
||
| 429 | </div> |
||
| 430 | </div> |
||
| 431 | </div> |
||
| 432 | |||
| 433 | <!-- System Status Card --> |
||
| 434 | <div class="col-lg-6"> |
||
| 435 | <div class="card card-primary"> |
||
| 436 | <div class="card-header"> |
||
| 437 | <h3 class="card-title"> |
||
| 438 | <i class="fas fa-server"></i> |
||
| 439 | <?php echo $lang->get('admin_tasks_status'); ?> |
||
| 440 | </h3> |
||
| 441 | <div class="card-tools"> |
||
| 442 | <span class="badge badge-primary" id="status-refresh-countdown">60s</span> |
||
| 443 | </div> |
||
| 444 | </div> |
||
| 445 | <div class="card-body"> |
||
| 446 | <div class="row mt-3"> |
||
| 447 | <div class="col-6"> |
||
| 448 | <div class="description-block"> |
||
| 449 | <h5 class="description-header" id="system-last-cron">--</h5> |
||
| 450 | <span class="description-text"><?php echo $lang->get('system_last_cron'); ?></span> |
||
| 451 | </div> |
||
| 452 | </div> |
||
| 453 | <div class="col-6"> |
||
| 454 | <div class="description-block"> |
||
| 455 | <h5 class="description-header" id="system-tasks">-</h5> |
||
| 456 | <span class="description-text"><?php echo $lang->get('tasks_queue'); ?></span> |
||
| 457 | </div> |
||
| 458 | </div> |
||
| 459 | </div> |
||
| 460 | <div class="row mt-3"> |
||
| 461 | <div class="col-12"> |
||
| 462 | <div class="alert alert-warning hidden" id="task_duration_status"></div> |
||
| 463 | </div> |
||
| 464 | </div> |
||
| 465 | <?php |
||
| 466 | // Instantiate the adapter and repository |
||
| 467 | try { |
||
| 468 | // Get last cron execution timestamp |
||
| 469 | DB::query( |
||
| 470 | 'SELECT valeur |
||
| 471 | FROM ' . prefixTable('misc') . ' |
||
| 472 | WHERE type = %s AND intitule = %s and valeur >= %d', |
||
| 473 | 'admin', |
||
| 474 | 'last_cron_exec', |
||
| 475 | time() - 600 // max 10 minutes |
||
| 476 | ); |
||
| 477 | |||
| 478 | if (DB::count() === 0) { |
||
| 479 | ?> |
||
| 480 | <div class="row mt-3"> |
||
| 481 | <div class="col-12"> |
||
| 482 | <div class="callout callout-info alert-dismissible mt-3" role="alert"> |
||
| 483 | <h5><i class="fa-solid fa-info mr-2"></i><?php echo $lang->get('information'); ?></h5> |
||
| 484 | <?php echo str_replace("#teampass_path#", $SETTINGS['cpassman_dir'], $lang->get('tasks_information')); ?> |
||
| 485 | <div class="mt-2"> |
||
| 486 | <a href="index.php?page=tasks#settings" class="btn btn-info" role="button"><i class="fa-solid fa-arrow-up-right-from-square mr-2"></i><?php echo $lang->get('open_tasks_settings'); ?></a> |
||
| 487 | </div> |
||
| 488 | </div> |
||
| 489 | </div> |
||
| 490 | </div> |
||
| 491 | <?php |
||
| 492 | } |
||
| 493 | } |
||
| 494 | catch (Exception $e) { |
||
| 495 | if (defined('LOG_TO_SERVER') && LOG_TO_SERVER === true) { |
||
| 496 | error_log('TEAMPASS Error - admin page - '.$e->getMessage()); |
||
| 497 | } |
||
| 498 | echo 'An error occurred. Please refer to server logs.'; |
||
| 499 | } |
||
| 500 | ?> |
||
| 501 | </div> |
||
| 502 | <div class="card-footer"> |
||
| 503 | <a href="index.php?page=tasks#settings" class="btn btn-sm btn-primary"> |
||
| 504 | <?php echo $lang->get('view_tasks'); ?> |
||
| 505 | </a> |
||
| 506 | </div> |
||
| 507 | <div class="overlay" id="loading-status" style="display:none;"> |
||
| 508 | <i class="fas fa-sync fa-spin"></i> |
||
| 509 | </div> |
||
| 510 | </div> |
||
| 511 | </div> |
||
| 512 | </div> |
||
| 513 | |||
| 514 | <?php |
||
| 515 | // Get server information |
||
| 516 | $serverVersionFull = DB::serverVersion(); |
||
| 517 | $dbType = (stripos($serverVersionFull, 'MariaDB') !== false) ? 'MariaDB' : 'MySQL'; |
||
| 518 | $versionParts = explode('-', $serverVersionFull); |
||
| 519 | $dbVersion = $versionParts[0]; |
||
| 520 | |||
| 521 | // Get database size |
||
| 522 | $dbSize = DB::queryFirstField( |
||
| 523 | "SELECT ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size |
||
| 524 | FROM information_schema.TABLES |
||
| 525 | WHERE table_schema = DATABASE()" |
||
| 526 | ); |
||
| 527 | $dbSizeFormatted = $dbSize . ' MB'; |
||
| 528 | |||
| 529 | // Get other PHP info |
||
| 530 | $phpVersion = phpversion(); |
||
| 531 | $memoryLimit = ini_get('memory_limit'); |
||
| 532 | $memoryUsage = round(memory_get_usage() / 1024, 2) . ' KB'; |
||
| 533 | $maxExecutionTime = ini_get('max_execution_time') . 's'; |
||
| 534 | $maxUploadSize = ini_get('upload_max_filesize'); |
||
| 535 | |||
| 536 | // Get OS info |
||
| 537 | $osInfo = php_uname('s') . ' ' . php_uname('r'); |
||
| 538 | |||
| 539 | // Get timezone |
||
| 540 | $timezone = date_default_timezone_get(); |
||
| 541 | $serverTime = date('H:i:s'); |
||
| 542 | |||
| 543 | // Check internet connection (optional) |
||
| 544 | $internetStatus = @fsockopen("www.google.com", 80, $errno, $errstr, 3); |
||
| 545 | $internetConnected = ($internetStatus !== false); |
||
| 546 | if ($internetStatus) { |
||
|
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
| 547 | fclose($internetStatus); |
||
| 548 | } |
||
| 549 | ?> |
||
| 550 | |||
| 551 | <!-- Server Information Row --> |
||
| 552 | <div class="row"> |
||
| 553 | <div class="col-lg-12"> |
||
| 554 | <div class="card card-info"> |
||
| 555 | <div class="card-header"> |
||
| 556 | <h3 class="card-title"> |
||
| 557 | <i class="fas fa-server"></i> |
||
| 558 | Server Information |
||
| 559 | </h3> |
||
| 560 | </div> |
||
| 561 | <div class="card-body"> |
||
| 562 | <div class="row"> |
||
| 563 | <!-- System & Network --> |
||
| 564 | <div class="col-lg-3 col-md-6 col-sm-12"> |
||
| 565 | <h6 class="text-muted mb-3"> |
||
| 566 | <i class="fas fa-desktop text-info"></i> System & Network |
||
| 567 | </h6> |
||
| 568 | <div class="mb-2"> |
||
| 569 | <i class="fab fa-linux text-primary"></i> |
||
| 570 | <small class="text-muted">OS:</small> |
||
| 571 | <span class="float-right"><strong><?php echo $osInfo; ?></strong></span> |
||
| 572 | </div> |
||
| 573 | <div class="mb-2"> |
||
| 574 | <i class="fas fa-globe text-<?php echo $internetConnected ? 'success' : 'danger'; ?>"></i> |
||
| 575 | <small class="text-muted">Internet:</small> |
||
| 576 | <span class="float-right"> |
||
| 577 | <span class="badge badge-<?php echo $internetConnected ? 'success' : 'danger'; ?>"> |
||
| 578 | <i class="fas fa-<?php echo $internetConnected ? 'check' : 'times'; ?>"></i> |
||
| 579 | <?php echo $internetConnected ? 'Connected' : 'Disconnected'; ?> |
||
| 580 | </span> |
||
| 581 | </span> |
||
| 582 | </div> |
||
| 583 | </div> |
||
| 584 | |||
| 585 | <!-- PHP Configuration --> |
||
| 586 | <div class="col-lg-3 col-md-6 col-sm-12"> |
||
| 587 | <h6 class="text-muted mb-3"> |
||
| 588 | <i class="fab fa-php text-info"></i> PHP Configuration |
||
| 589 | </h6> |
||
| 590 | <div class="mb-2"> |
||
| 591 | <i class="fas fa-code text-primary"></i> |
||
| 592 | <small class="text-muted">Version:</small> |
||
| 593 | <span class="float-right"><strong><?php echo $phpVersion; ?></strong></span> |
||
| 594 | </div> |
||
| 595 | <div class="mb-2"> |
||
| 596 | <i class="fas fa-memory text-warning"></i> |
||
| 597 | <small class="text-muted">Memory limit:</small> |
||
| 598 | <span class="float-right"><strong><?php echo $memoryLimit; ?></strong></span> |
||
| 599 | </div> |
||
| 600 | <div class="mb-2"> |
||
| 601 | <i class="fas fa-chart-area text-success"></i> |
||
| 602 | <small class="text-muted">Memory usage:</small> |
||
| 603 | <span class="float-right"><strong><?php echo $memoryUsage; ?></strong></span> |
||
| 604 | </div> |
||
| 605 | </div> |
||
| 606 | |||
| 607 | <!-- PHP Limits --> |
||
| 608 | <div class="col-lg-3 col-md-6 col-sm-12"> |
||
| 609 | <h6 class="text-muted mb-3"> |
||
| 610 | <i class="fas fa-sliders-h text-info"></i> PHP Limits |
||
| 611 | </h6> |
||
| 612 | <div class="mb-2"> |
||
| 613 | <i class="fas fa-clock text-warning"></i> |
||
| 614 | <small class="text-muted">Max execution:</small> |
||
| 615 | <span class="float-right"><strong><?php echo $maxExecutionTime; ?></strong></span> |
||
| 616 | </div> |
||
| 617 | <div class="mb-2"> |
||
| 618 | <i class="fas fa-file-upload text-primary"></i> |
||
| 619 | <small class="text-muted">Max upload:</small> |
||
| 620 | <span class="float-right"><strong><?php echo $maxUploadSize; ?></strong></span> |
||
| 621 | </div> |
||
| 622 | </div> |
||
| 623 | |||
| 624 | <!-- Database & Time --> |
||
| 625 | <div class="col-lg-3 col-md-6 col-sm-12"> |
||
| 626 | <h6 class="text-muted mb-3"> |
||
| 627 | <i class="fas fa-database text-info"></i> Database & Time |
||
| 628 | </h6> |
||
| 629 | <div class="mb-2"> |
||
| 630 | <i class="fas fa-server text-success"></i> |
||
| 631 | <small class="text-muted"><?php echo $dbType; ?>:</small> |
||
| 632 | <span class="float-right"><strong><?php echo $dbVersion; ?></strong></span> |
||
| 633 | </div> |
||
| 634 | <div class="mb-2"> |
||
| 635 | <i class="fas fa-hdd text-warning"></i> |
||
| 636 | <small class="text-muted">DB size:</small> |
||
| 637 | <span class="float-right"><strong><?php echo $dbSizeFormatted; ?></strong></span> |
||
| 638 | </div> |
||
| 639 | <div class="mb-2"> |
||
| 640 | <i class="fas fa-clock text-primary"></i> |
||
| 641 | <small class="text-muted">Server time:</small> |
||
| 642 | <span class="float-right"><strong><?php echo $serverTime; ?></strong></span> |
||
| 643 | </div> |
||
| 644 | <div class="mb-2"> |
||
| 645 | <i class="fas fa-map-marker-alt text-danger"></i> |
||
| 646 | <small class="text-muted">Timezone:</small> |
||
| 647 | <span class="float-right"><strong><?php echo $timezone; ?></strong></span> |
||
| 648 | </div> |
||
| 649 | </div> |
||
| 650 | </div> |
||
| 651 | </div> |
||
| 652 | </div> |
||
| 653 | </div> |
||
| 654 | </div> |
||
| 655 | |||
| 656 | <!-- Sponsoring Row --> |
||
| 657 | <div class="row"> |
||
| 658 | <div class="col-lg-12"> |
||
| 659 | <div class="card card-outline card-primary"> |
||
| 660 | <div class="card-header"> |
||
| 661 | <h3 class="card-title"> |
||
| 662 | <i class="fas fa-heart text-danger"></i> |
||
| 663 | <?php echo $lang->get('admin_support_teampass'); ?> |
||
| 664 | </h3> |
||
| 665 | </div> |
||
| 666 | <div class="card-body"> |
||
| 667 | <div class="row align-items-center"> |
||
| 668 | <div class="col-md-8"> |
||
| 669 | <p class="mb-2"> |
||
| 670 | <strong><?php echo $lang->get('admin_support_message'); ?></strong> |
||
| 671 | </p> |
||
| 672 | <p class="text-muted mb-3"> |
||
| 673 | <?php echo $lang->get('admin_support_description'); ?> |
||
| 674 | </p> |
||
| 675 | </div> |
||
| 676 | <div class="col-md-4 text-center"> |
||
| 677 | <a href="https://github.com/sponsors/nilsteampassnet" target="_blank" class="btn btn-danger btn-lg"> |
||
| 678 | <i class="fab fa-github"></i> <?php echo $lang->get('admin_support_github_sponsors'); ?> |
||
| 679 | </a> |
||
| 680 | <br> |
||
| 681 | <a href="https://www.paypal.com/donate/?hosted_button_id=XUVWYJ7J92X6L" target="_blank" class="btn btn-primary btn-lg mt-2"> |
||
| 682 | <i class="fab fa-paypal"></i> <?php echo $lang->get('admin_support_paypal'); ?> |
||
| 683 | </a> |
||
| 684 | <p class="text-muted mt-3 small"> |
||
| 685 | <i class="fas fa-users"></i> <?php echo $lang->get('admin_support_thank_you'); ?> |
||
| 686 | </p> |
||
| 687 | </div> |
||
| 688 | </div> |
||
| 689 | </div> |
||
| 690 | </div> |
||
| 691 | </div> |
||
| 692 | </div> |
||
| 693 | |||
| 694 | </div> |
||
| 695 | |||
| 696 | </div> |
||
| 697 | </div> |
||
| 698 | </div> |
||
| 699 | |||
| 700 | </div> |
||
| 701 | </section> |
||
| 702 | |||
| 703 | <!-- Info Modal --> |
||
| 704 | <div class="modal fade" id="info-modal" tabindex="-1" role="dialog" aria-labelledby="info-modal-title" aria-hidden="true"> |
||
| 705 | <div class="modal-dialog modal-dialog-centered modal-lg" role="document"> |
||
| 706 | <div class="modal-content"> |
||
| 707 | <div class="modal-header bg-info"> |
||
| 708 | <h5 class="modal-title" id="info-modal-title"> |
||
| 709 | <i class="fas fa-info-circle"></i> Information |
||
| 710 | </h5> |
||
| 711 | <button type="button" class="close" data-dismiss="modal" aria-label="Close"> |
||
| 712 | <span aria-hidden="true">×</span> |
||
| 713 | </button> |
||
| 714 | </div> |
||
| 715 | <div class="modal-body" id="info-modal-body"> |
||
| 716 | <!-- Content will be inserted here --> |
||
| 717 | </div> |
||
| 718 | <div class="modal-footer"> |
||
| 719 | <button type="button" class="btn btn-secondary" data-dismiss="modal"> |
||
| 720 | <i class="fas fa-times"></i> Close |
||
| 721 | </button> |
||
| 722 | </div> |
||
| 723 | </div> |
||
| 724 | </div> |
||
| 725 | </div> |
||
| 726 |