فهرست منبع

Fix null deprecation and admin View as Client link

- admin_dashboard.php: add ?? '' fallback on reference and client_email to prevent htmlspecialchars(null) deprecation
- progress.php: admin bypass — valid HTTP Basic Auth skips clientid/token validation, so the admin dashboard's View as Client link works without a signed URL

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Benjamin Harris 2 هفته پیش
والد
کامیت
a2a944e0ee
2فایلهای تغییر یافته به همراه31 افزوده شده و 19 حذف شده
  1. 2 2
      contracts/admin_dashboard.php
  2. 29 17
      contracts/progress.php

+ 2 - 2
contracts/admin_dashboard.php

@@ -85,8 +85,8 @@ $applications = $stmt->fetchAll();
                     <?php foreach ($applications as $app): ?>
                     <tr>
                         <td><?= $app['id'] ?></td>
-                        <td><?= htmlspecialchars($app['reference']) ?></td>
-                        <td><?= htmlspecialchars($app['client_email']) ?></td>
+                        <td><?= htmlspecialchars($app['reference'] ?? '', ENT_QUOTES, 'UTF-8') ?></td>
+                        <td><?= htmlspecialchars($app['client_email'] ?? '', ENT_QUOTES, 'UTF-8') ?></td>
                         <td>
                             <a href="edit_application.php?id=<?= $app['id'] ?>" class="btn btn-sm btn-primary">Edit Timeline</a>
                             <a href="progress.php?id=<?= $app['id'] ?>" class="btn btn-sm btn-outline-secondary">View as Client</a>

+ 29 - 17
contracts/progress.php

@@ -226,25 +226,37 @@ function stage_icon_for(string $title): string {
     return 'bi-flag';
 }
 
-// --- Require signed token from Contracts Admin link ---
-$clientid = $_GET['clientid'] ?? '';
-$token    = $_GET['token']    ?? '';
-
-if (!preg_match('/^[A-Za-z0-9_-]+$/', $clientid)) {
-    http_response_code(400);
-    exit('Bad link (clientid).');
-}
-if ($token === '') {
-    http_response_code(403);
-    exit('Missing token.');
-}
+// Admin bypass: valid HTTP Basic Auth skips the client token check
+$_au = $cfg['admin_user'] ?? '';
+$_ap = $cfg['admin_pass'] ?? '';
+$isAdmin = $_au !== '' && $_ap !== ''
+    && isset($_SERVER['PHP_AUTH_USER'])
+    && $_SERVER['PHP_AUTH_USER'] === $_au
+    && ($_SERVER['PHP_AUTH_PW'] ?? '') === $_ap;
+
+if (!$isAdmin) {
+    // --- Require signed token from Contracts Admin link ---
+    $clientid = $_GET['clientid'] ?? '';
+    $token    = $_GET['token']    ?? '';
+
+    if (!preg_match('/^[A-Za-z0-9_-]+$/', $clientid)) {
+        http_response_code(400);
+        exit('Bad link (clientid).');
+    }
+    if ($token === '') {
+        header('WWW-Authenticate: Basic realm="Modulos Contracts Admin"');
+        http_response_code(403);
+        exit('Missing token.');
+    }
 
-// Build expected token from the .md front matter secret
-$expected = progress_expected_token($clientid, $app_id);
-if (!$expected || !hash_equals($expected, $token)) {
-    http_response_code(403);
-    exit('Invalid or expired link.');
+    // Build expected token from the .md front matter secret
+    $expected = progress_expected_token($clientid, $app_id);
+    if (!$expected || !hash_equals($expected, $token)) {
+        http_response_code(403);
+        exit('Invalid or expired link.');
+    }
 }
+unset($_au, $_ap);
 
 ?>
 <!doctype html>