diff --git a/web/api/db.php b/web/api/db.php index f8f0084..3cc741b 100644 --- a/web/api/db.php +++ b/web/api/db.php @@ -61,3 +61,16 @@ function error_out(string $message, int $status = 400): never { json_out(['error' => $message], $status); } + +/** + * Aborts with 400 if no Clickatell API key has been configured. + */ +function require_api_key(): void +{ + $stmt = db()->prepare("SELECT setting_value FROM `system` WHERE setting_name = 'clickatell_api_key'"); + $stmt->execute(); + $key = $stmt->fetchColumn(); + if ($key === false || trim((string) $key) === '') { + error_out('No Clickatell API key is configured. Set one in Admin → Clickatell Settings before sending or scheduling messages.', 400); + } +} diff --git a/web/api/schedule.php b/web/api/schedule.php index 724da04..f449a23 100644 --- a/web/api/schedule.php +++ b/web/api/schedule.php @@ -42,6 +42,8 @@ function handle_get(): never function handle_post(): never { + require_api_key(); + $body = json_body(); $templateId = (int) ($body['template_id'] ?? 0); $mode = (string) ($body['mode'] ?? ''); @@ -104,6 +106,8 @@ function handle_post(): never function handle_put(): never { + require_api_key(); + $id = (int) ($_GET['id'] ?? 0); if ($id <= 0) { error_out('Missing or invalid id'); diff --git a/web/api/send-now.php b/web/api/send-now.php index 56b7733..6494b4b 100644 --- a/web/api/send-now.php +++ b/web/api/send-now.php @@ -16,6 +16,8 @@ if ($_SERVER['REQUEST_METHOD'] !== 'POST') { // } try { + require_api_key(); + $body = json_body(); $customBody = trim((string) ($body['message'] ?? '')); $templateId = isset($body['template_id']) ? (int) $body['template_id'] : null; diff --git a/web/schedule.html b/web/schedule.html index c4b88d3..b041bf0 100644 --- a/web/schedule.html +++ b/web/schedule.html @@ -117,6 +117,11 @@ Sandbox mode is active — texts are tagged as a test and excluded from cost calculations. + @@ -516,6 +521,16 @@ } checkAuth(); document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible') checkAuth(); }); + + async function checkApiKey() { + try { + const r = await fetch('/api/settings.php?key=clickatell_api_key').then(res => res.json()); + const missing = !r.set; + document.getElementById('noApiKeyBanner').style.display = missing ? '' : 'none'; + document.getElementById('addScheduleBtn').disabled = missing; + } catch { } + } + checkApiKey(); diff --git a/web/send-now.html b/web/send-now.html index 6ac5125..8a132e1 100644 --- a/web/send-now.html +++ b/web/send-now.html @@ -103,6 +103,11 @@ Sandbox mode is active — texts are tagged as a test and excluded from cost calculations. + `; } finally { - sendBtn.disabled = msgEl.value.trim() === ''; + sendBtn.disabled = msgEl.value.trim() === '' || noApiKey; sendBtn.innerHTML = 'Send to ' + countSpan.textContent + ' attendees'; } }); @@ -384,6 +390,16 @@ } checkAuth(); document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible') checkAuth(); }); + + async function checkApiKey() { + try { + const r = await fetch('/api/settings.php?key=clickatell_api_key').then(res => res.json()); + noApiKey = !r.set; + document.getElementById('noApiKeyBanner').style.display = noApiKey ? '' : 'none'; + if (noApiKey) document.getElementById('sendBtn').disabled = true; + } catch { } + } + checkApiKey();