diff --git a/CHANGELOG.md b/CHANGELOG.md index 833d363..f9c80a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,10 @@ - Adjusted endpoint paths to match controller filenames - Fix FolderController readOnly create folder permission +### Additional changes + +- Extend clean up expired shared entries + --- ## Changes 4/30/2025 v1.2.8 diff --git a/public/api/admin/readMetadata.php b/public/api/admin/readMetadata.php index 5a5baae..77f7902 100644 --- a/public/api/admin/readMetadata.php +++ b/public/api/admin/readMetadata.php @@ -3,42 +3,61 @@ require_once __DIR__ . '/../../../config/config.php'; -// Simple auth‐check: only admins may read these +// Only admins may read these if (empty($_SESSION['isAdmin']) || $_SESSION['isAdmin'] !== true) { http_response_code(403); - echo json_encode(['error'=>'Forbidden']); + echo json_encode(['error' => 'Forbidden']); exit; } -// Expect a ?file=share_links.json or share_folder_links.json +// Must supply ?file=share_links.json or share_folder_links.json if (empty($_GET['file'])) { http_response_code(400); - echo json_encode(['error'=>'Missing `file` parameter']); + echo json_encode(['error' => 'Missing `file` parameter']); exit; } $file = basename($_GET['file']); -$allowed = ['share_links.json','share_folder_links.json']; +$allowed = ['share_links.json', 'share_folder_links.json']; if (!in_array($file, $allowed, true)) { http_response_code(403); - echo json_encode(['error'=>'Invalid file requested']); + echo json_encode(['error' => 'Invalid file requested']); exit; } $path = META_DIR . $file; if (!file_exists($path)) { - http_response_code(404); - echo json_encode((object)[]); // return empty object + // Return empty object so JS sees `{}` not an error + http_response_code(200); + header('Content-Type: application/json'); + echo json_encode((object)[]); exit; } -$data = file_get_contents($path); -$json = json_decode($data, true); -if (json_last_error() !== JSON_ERROR_NONE) { +$jsonData = file_get_contents($path); +$data = json_decode($jsonData, true); +if (json_last_error() !== JSON_ERROR_NONE || !is_array($data)) { http_response_code(500); - echo json_encode(['error'=>'Corrupted JSON']); + echo json_encode(['error' => 'Corrupted JSON']); exit; } +// ——— Clean up expired entries ——— +$now = time(); +$changed = false; +foreach ($data as $token => $entry) { + if (!empty($entry['expires']) && $entry['expires'] < $now) { + unset($data[$token]); + $changed = true; + } +} +if ($changed) { + // overwrite file with cleaned data + file_put_contents($path, json_encode($data, JSON_PRETTY_PRINT)); +} + +// ——— Send cleaned data back ——— +http_response_code(200); header('Content-Type: application/json'); -echo json_encode($json); \ No newline at end of file +echo json_encode($data); +exit; \ No newline at end of file diff --git a/public/js/adminPanel.js b/public/js/adminPanel.js index 1296f7c..cb4a93f 100644 --- a/public/js/adminPanel.js +++ b/public/js/adminPanel.js @@ -184,49 +184,63 @@ function loadShareLinksSection() { const container = document.getElementById("shareLinksContent"); container.textContent = t("loading") + "..."; - // Helper to fetch a metadata file or return {} on any error - const fetchMeta = file => - fetch(`/api/admin/readMetadata.php?file=${file}`, { credentials: "include" }) - .then(r => r.ok ? r.json() : {}) // non-2xx → treat as empty - .catch(() => ({})); + // helper: fetch one metadata file, but never throw — + // on non-2xx (including 404) or network error, resolve to {} + function fetchMeta(fileName) { + return fetch(`/api/admin/readMetadata.php?file=${encodeURIComponent(fileName)}`, { + credentials: "include" + }) + .then(resp => { + if (!resp.ok) { + // 404 or any other non-OK → treat as empty + return {}; + } + return resp.json(); + }) + .catch(() => { + // network failure, parse error, etc → also empty + return {}; + }); + } Promise.all([ - fetchMeta("share_folder_links.json"), - fetchMeta("share_links.json") - ]) + fetchMeta("share_folder_links.json"), + fetchMeta("share_links.json") + ]) .then(([folders, files]) => { - // If nothing at all, show a friendly message - if (Object.keys(folders).length === 0 && Object.keys(files).length === 0) { - container.textContent = t("no_shared_links_available"); + // if *both* are empty, show "no shared links" + const hasAny = Object.keys(folders).length || Object.keys(files).length; + if (!hasAny) { + container.innerHTML = `
${t("no_shared_links_available")}
`; return; } let html = `