| @@ -100,8 +100,12 @@ | ||
| 100 | 100 | } |
| 101 | 101 | |
| 102 | 102 | // Check temporary access (transient) |
| 103 | 103 | if ($this->has_transient_access()) { |
| 104 | + // Sliding window: renew the access window itself, not just the | |
| 105 | + // decorative activity timestamp, so an admin actively using the | |
| 106 | + // tab is not cut off exactly at grant-time + timeout. | |
| 107 | + set_transient($this->get_transient_key(), 'granted', $this->transient_timeout); | |
| 104 | 108 | // Refresh transient activity |
| 105 | 109 | $this->update_activity(); |
| 106 | 110 | return true; |
| 107 | 111 | } |
| @@ -362,10 +366,14 @@ | ||
| 362 | 366 | if (!is_array($valid_passwords)) { |
| 363 | 367 | $valid_passwords = array($valid_passwords); |
| 364 | 368 | } |
| 365 | 369 | |
| 366 | - // Remove empty passwords | |
| 367 | - $valid_passwords = array_filter($valid_passwords); | |
| 370 | + // Remove unset/empty passwords, but keep the string '0' — a | |
| 371 | + // truthiness filter would silently drop a configured password of | |
| 372 | + // "0" and make it impossible to authenticate with. | |
| 373 | + $valid_passwords = array_filter($valid_passwords, function ($p) { | |
| 374 | + return null !== $p && '' !== $p; | |
| 375 | + }); | |
| 368 | 376 | |
| 369 | 377 | if (empty($valid_passwords)) { |
| 370 | 378 | return false; |
| 371 | 379 | } |
| @@ -437,8 +445,14 @@ | ||
| 437 | 445 | * @param string $context Authentication context |
| 438 | 446 | * @return bool True if user has access, false otherwise |
| 439 | 447 | */ |
| 440 | 448 | public static function user_has_access($user_id, $context = 'default') { |
| 449 | + $user_id = absint($user_id); | |
| 450 | + if (!$user_id) { | |
| 451 | + return false; | |
| 452 | + } | |
| 453 | + | |
| 441 | 454 | $auth = new self($context); |
| 455 | + $auth->user_id = $user_id; | |
| 442 | 456 | return $auth->has_access(); |
| 443 | 457 | } |
| 444 | 458 | } |