Use shared auth and proxy Home Assistant webhooks
This commit is contained in:
+54
-87
@@ -1,11 +1,6 @@
|
||||
<?php
|
||||
// Apache 환경 차단
|
||||
if (isset($_SERVER['SERVER_SOFTWARE']) && stripos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false) {
|
||||
http_response_code(403);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['error' => 'Access forbidden: Apache environment is not allowed']);
|
||||
exit;
|
||||
}
|
||||
require_once __DIR__ . '/../../common/auth.php';
|
||||
require_once __DIR__ . '/../../common/ha.php';
|
||||
|
||||
// POST 전용 검사
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
@@ -15,69 +10,47 @@ if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
exit;
|
||||
}
|
||||
|
||||
// JSON 요청 검사
|
||||
$content_type = $_SERVER['CONTENT_TYPE'] ?? '';
|
||||
if (stripos($content_type, 'application/json') === false) {
|
||||
http_response_code(415); // Unsupported Media Type
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['error' => 'Unsupported Content-Type. application/json required']);
|
||||
exit;
|
||||
}
|
||||
|
||||
function get_authorization_header() {
|
||||
if (!empty($_SERVER['HTTP_AUTHORIZATION'])) {
|
||||
return trim($_SERVER['HTTP_AUTHORIZATION']);
|
||||
} elseif (function_exists('apache_request_headers')) {
|
||||
foreach (apache_request_headers() as $key => $value) {
|
||||
if (strcasecmp($key, 'Authorization') === 0) {
|
||||
return trim($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
$auth_header = get_authorization_header();
|
||||
if (!$auth_header || !preg_match('/^Bearer\s+(\S+)$/', $auth_header, $matches)) {
|
||||
http_response_code(401);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['error' => 'Unauthorized: Missing or invalid Authorization header']);
|
||||
exit;
|
||||
}
|
||||
|
||||
$allowed_password = 'XBv9z1IGqPUdtVf7DABFA16H0E154LJS';
|
||||
$password = $matches[1];
|
||||
if ($password !== $allowed_password) {
|
||||
http_response_code(401);
|
||||
header('Content-Type: application/json');
|
||||
echo json_encode(['error' => 'Unauthorized: Invalid token']);
|
||||
exit;
|
||||
}
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||
header('Expires: 0');
|
||||
|
||||
$baseUrl = "https://ha.seoul.chaegeon.com/api/states";
|
||||
$headers = [
|
||||
"Authorization: Bearer REDACTED_HA_TOKEN",
|
||||
"Content-Type: application/json"
|
||||
];
|
||||
custom_require_auth();
|
||||
|
||||
$requestData = custom_read_request_data();
|
||||
if (isset($_GET['action']) && $_GET['action'] === 'webhook') {
|
||||
$name = (string)($requestData['name'] ?? '');
|
||||
$allowed = [
|
||||
'auto_on' => 'find_auto_on',
|
||||
'auto_off' => 'find_auto_off',
|
||||
'auto_tick' => 'find_auto_tick',
|
||||
'force_update' => 'find_force_update',
|
||||
];
|
||||
|
||||
if (!isset($allowed[$name])) {
|
||||
custom_json(['result' => 'invalid_webhook'], 400);
|
||||
}
|
||||
|
||||
$ok = custom_ha_webhook($allowed[$name]);
|
||||
custom_json(['result' => $ok ? 'ok' : 'fail'], $ok ? 200 : 502);
|
||||
}
|
||||
|
||||
$config = custom_config();
|
||||
$entities = $config['entities'];
|
||||
|
||||
// 엔드포인트 URL
|
||||
$deviceUrl = "$baseUrl/device_tracker.seocaegeonyi_z_fold7";
|
||||
$geoUrl = "$baseUrl/sensor.seocaegeonyi_z_fold7_geocoded_location";
|
||||
$batteryStateUrl = "$baseUrl/sensor.seocaegeonyi_z_fold7_battery_state";
|
||||
$batteryLevelUrl = "$baseUrl/sensor.seocaegeonyi_z_fold7_battery_level";
|
||||
$watchBatteryStateUrl = "$baseUrl/sensor.seocaegeonyi_z_fold7_watch_battery_state";
|
||||
$watchBatteryLevelUrl = "$baseUrl/sensor.seocaegeonyi_z_fold7_watch_battery_level";
|
||||
$activityUrl = "$baseUrl/sensor.seocaegeonyi_z_fold7_detected_activity";
|
||||
$connectionUrl = "$baseUrl/sensor.seocaegeonyi_z_fold7_network_type";
|
||||
$fascendedUrl = "$baseUrl/sensor.seocaegeonyi_z_fold7_daily_floors";
|
||||
$fdescendedUrl = "$baseUrl/sensor.seocaegeonyi_z_fold7_daily_floors";
|
||||
$stepsUrl = "$baseUrl/sensor.seocaegeonyi_z_fold7_daily_steps";
|
||||
$distanceUrl = "$baseUrl/sensor.seocaegeonyi_z_fold7_daily_distance";
|
||||
$triggerUrl = "$baseUrl/sensor.seocaegeonyi_z_fold7_last_update_trigger";
|
||||
$deviceUrl = $entities['device'];
|
||||
$geoUrl = $entities['geo'];
|
||||
$batteryStateUrl = $entities['battery_state'];
|
||||
$batteryLevelUrl = $entities['battery_level'];
|
||||
$watchBatteryStateUrl = $entities['watch_battery_state'];
|
||||
$watchBatteryLevelUrl = $entities['watch_battery_level'];
|
||||
$activityUrl = $entities['activity'];
|
||||
$connectionUrl = $entities['connection'];
|
||||
$fascendedUrl = $entities['daily_floors'];
|
||||
$fdescendedUrl = $entities['daily_floors'];
|
||||
$stepsUrl = $entities['daily_steps'];
|
||||
$distanceUrl = $entities['daily_distance'];
|
||||
$triggerUrl = $entities['trigger'];
|
||||
|
||||
// GET 파라미터 읽기
|
||||
$startParam = $_GET['startTime'] ?? null;
|
||||
@@ -97,34 +70,28 @@ if ($startParam && $endParam) {
|
||||
}
|
||||
|
||||
// API URL 생성
|
||||
$historyUrl = "https://ha.seoul.chaegeon.com/api/history/period/{$startTime}?filter_entity_id=device_tracker.seocaegeonyi_z_fold7&end_time={$endTime}";
|
||||
$historyEndpoint = "/history/period/{$startTime}?filter_entity_id=" . rawurlencode($entities['device']) . "&end_time={$endTime}";
|
||||
|
||||
// 공통 요청 함수
|
||||
function getData($url, $headers) {
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return json_decode($response, true);
|
||||
function getData($entityId) {
|
||||
return custom_ha_state('seoul', $entityId) ?? [];
|
||||
}
|
||||
|
||||
// 데이터 불러오기
|
||||
$deviceData = getData($deviceUrl, $headers);
|
||||
$geoData = getData($geoUrl, $headers);
|
||||
$batteryStateData = getData($batteryStateUrl, $headers);
|
||||
$batteryLevelData = getData($batteryLevelUrl, $headers);
|
||||
$watchBatteryStateData = getData($watchBatteryStateUrl, $headers);
|
||||
$watchBatteryLevelData = getData($watchBatteryLevelUrl, $headers);
|
||||
$activityData = getData($activityUrl, $headers);
|
||||
$connectionData = getData($connectionUrl, $headers);
|
||||
$ascendedData = getData($fascendedUrl, $headers);
|
||||
$descendedData = getData($fdescendedUrl, $headers);
|
||||
$stepsData = getData($stepsUrl, $headers);
|
||||
$distanceData = getData($distanceUrl, $headers);
|
||||
$historyData = getData($historyUrl, $headers);
|
||||
$triggerData = getData($triggerUrl, $headers);
|
||||
$deviceData = getData($deviceUrl);
|
||||
$geoData = getData($geoUrl);
|
||||
$batteryStateData = getData($batteryStateUrl);
|
||||
$batteryLevelData = getData($batteryLevelUrl);
|
||||
$watchBatteryStateData = getData($watchBatteryStateUrl);
|
||||
$watchBatteryLevelData = getData($watchBatteryLevelUrl);
|
||||
$activityData = getData($activityUrl);
|
||||
$connectionData = getData($connectionUrl);
|
||||
$ascendedData = getData($fascendedUrl);
|
||||
$descendedData = getData($fdescendedUrl);
|
||||
$stepsData = getData($stepsUrl);
|
||||
$distanceData = getData($distanceUrl);
|
||||
$historyData = custom_ha_request('seoul', 'GET', $historyEndpoint) ?? [];
|
||||
$triggerData = getData($triggerUrl);
|
||||
|
||||
// 경로 기록
|
||||
$path = [];
|
||||
|
||||
Reference in New Issue
Block a user