Add public availability API and settings panel
Public saatavuus endpoint with API key + CORS protection for cuitunet.fi website integration. Admin settings tab for API key management and testing. Includes standalone widget page. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
137
api.php
137
api.php
@@ -17,6 +17,7 @@ define('ARCHIVE_FILE', DATA_DIR . '/archive.json');
|
||||
define('LEADS_FILE', DATA_DIR . '/leads.json');
|
||||
define('TOKENS_FILE', DATA_DIR . '/reset_tokens.json');
|
||||
define('RATE_FILE', DATA_DIR . '/login_attempts.json');
|
||||
define('CONFIG_FILE', DATA_DIR . '/config.json');
|
||||
define('SITE_URL', 'https://intra.cuitunet.fi');
|
||||
|
||||
// Sähköpostiasetukset
|
||||
@@ -88,6 +89,23 @@ function getClientIp(): string {
|
||||
return $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
|
||||
}
|
||||
|
||||
// ==================== CONFIG ====================
|
||||
|
||||
function loadConfig(): array {
|
||||
if (!file_exists(CONFIG_FILE)) return [];
|
||||
return json_decode(file_get_contents(CONFIG_FILE), true) ?: [];
|
||||
}
|
||||
|
||||
function saveConfig(array $config): void {
|
||||
file_put_contents(CONFIG_FILE, json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
|
||||
function normalizeAddress(string $addr): string {
|
||||
$addr = mb_strtolower(trim($addr));
|
||||
$addr = preg_replace('/\s+/', ' ', $addr);
|
||||
return $addr;
|
||||
}
|
||||
|
||||
// ==================== EMAIL ====================
|
||||
|
||||
function sendMail(string $to, string $subject, string $htmlBody): bool {
|
||||
@@ -247,6 +265,125 @@ function parseLiittymat(array $input): array {
|
||||
|
||||
switch ($action) {
|
||||
|
||||
// ---------- SAATAVUUS (julkinen API) ----------
|
||||
case 'saatavuus':
|
||||
// CORS - salli cuitunet.fi
|
||||
$config = loadConfig();
|
||||
$allowedOrigins = $config['cors_origins'] ?? ['https://cuitunet.fi', 'https://www.cuitunet.fi'];
|
||||
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
|
||||
if (in_array($origin, $allowedOrigins)) {
|
||||
header("Access-Control-Allow-Origin: $origin");
|
||||
header('Access-Control-Allow-Methods: GET, OPTIONS');
|
||||
header('Access-Control-Allow-Headers: Content-Type, X-Api-Key');
|
||||
}
|
||||
if ($method === 'OPTIONS') { http_response_code(204); break; }
|
||||
|
||||
// API-avain tarkistus
|
||||
$apiKey = $config['api_key'] ?? '';
|
||||
$providedKey = $_GET['key'] ?? ($_SERVER['HTTP_X_API_KEY'] ?? '');
|
||||
if (empty($apiKey) || $providedKey !== $apiKey) {
|
||||
http_response_code(403);
|
||||
echo json_encode(['error' => 'Virheellinen API-avain']);
|
||||
break;
|
||||
}
|
||||
|
||||
$query = normalizeAddress($_GET['osoite'] ?? '');
|
||||
$postinumero = trim($_GET['postinumero'] ?? '');
|
||||
|
||||
if (empty($query) && empty($postinumero)) {
|
||||
http_response_code(400);
|
||||
echo json_encode(['error' => 'Anna osoite tai postinumero']);
|
||||
break;
|
||||
}
|
||||
|
||||
$customers = loadCustomers();
|
||||
$matches = [];
|
||||
foreach ($customers as $c) {
|
||||
foreach ($c['liittymat'] ?? [] as $l) {
|
||||
$addr = normalizeAddress($l['asennusosoite'] ?? '');
|
||||
$zip = trim($l['postinumero'] ?? '');
|
||||
$city = mb_strtolower(trim($l['kaupunki'] ?? ''));
|
||||
$hit = false;
|
||||
|
||||
// Postinumero-haku
|
||||
if (!empty($postinumero) && $zip === $postinumero) {
|
||||
$hit = true;
|
||||
}
|
||||
|
||||
// Osoitehaku (sisältää haun)
|
||||
if (!empty($query) && !empty($addr)) {
|
||||
if (str_contains($addr, $query) || str_contains($query, $addr)) {
|
||||
$hit = true;
|
||||
}
|
||||
// Kadunnimi-match (ilman numeroa)
|
||||
$queryStreet = preg_replace('/\d+.*$/', '', $query);
|
||||
$addrStreet = preg_replace('/\d+.*$/', '', $addr);
|
||||
if (!empty(trim($queryStreet)) && !empty(trim($addrStreet)) && str_contains(trim($addrStreet), trim($queryStreet))) {
|
||||
$hit = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ($hit) {
|
||||
// Palauta VAIN osoitetieto ja nopeus - ei asiakastietoja
|
||||
$matches[] = [
|
||||
'osoite' => $l['asennusosoite'] ?? '',
|
||||
'postinumero' => $zip,
|
||||
'kaupunki' => $l['kaupunki'] ?? '',
|
||||
'nopeus' => $l['liittymanopeus'] ?? '',
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Poista duplikaatit (sama osoite eri asiakkailla)
|
||||
$unique = [];
|
||||
$seen = [];
|
||||
foreach ($matches as $m) {
|
||||
$key = normalizeAddress($m['osoite'] . $m['postinumero']);
|
||||
if (!isset($seen[$key])) {
|
||||
$unique[] = $m;
|
||||
$seen[$key] = true;
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode([
|
||||
'saatavilla' => count($unique) > 0,
|
||||
'kohteet' => $unique,
|
||||
'maara' => count($unique),
|
||||
]);
|
||||
break;
|
||||
|
||||
// ---------- CONFIG (admin) ----------
|
||||
case 'config':
|
||||
requireAdmin();
|
||||
echo json_encode(loadConfig());
|
||||
break;
|
||||
|
||||
case 'config_update':
|
||||
requireAdmin();
|
||||
if ($method !== 'POST') break;
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$config = loadConfig();
|
||||
if (isset($input['api_key'])) $config['api_key'] = trim($input['api_key']);
|
||||
if (isset($input['cors_origins'])) {
|
||||
$origins = array_filter(array_map('trim', explode("\n", $input['cors_origins'])));
|
||||
$config['cors_origins'] = array_values($origins);
|
||||
}
|
||||
saveConfig($config);
|
||||
addLog('config_update', '', '', 'Päivitti asetukset');
|
||||
echo json_encode($config);
|
||||
break;
|
||||
|
||||
case 'generate_api_key':
|
||||
requireAdmin();
|
||||
if ($method !== 'POST') break;
|
||||
$config = loadConfig();
|
||||
$config['api_key'] = bin2hex(random_bytes(16));
|
||||
saveConfig($config);
|
||||
addLog('config_update', '', '', 'Generoi uuden API-avaimen');
|
||||
echo json_encode($config);
|
||||
break;
|
||||
|
||||
// ---------- CAPTCHA ----------
|
||||
case 'captcha':
|
||||
$a = rand(1, 20);
|
||||
|
||||
Reference in New Issue
Block a user