add auth check
This commit is contained in:
+66
-1
@@ -1,6 +1,10 @@
|
||||
"""ReinLoop cloud-server endpoint configuration shared by core modules."""
|
||||
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
|
||||
import requests
|
||||
|
||||
from license_utils import get_verified_license
|
||||
|
||||
@@ -16,6 +20,7 @@ server_api_url = os.environ.get(
|
||||
# Compatibility alias used by existing modules. It points to the ReinLoop
|
||||
# Express server API, not a cloud-function endpoint.
|
||||
data_record_url = server_api_url
|
||||
device_api_url = f"{server_api_url.rstrip('/')}/device"
|
||||
_license = get_verified_license()
|
||||
_license_device_id = (_license or {}).get("device_id", "").strip()
|
||||
_environment_device_id = os.environ.get("REINLOOP_DEVICE_ID", "").strip()
|
||||
@@ -26,4 +31,64 @@ if _license_device_id and _environment_device_id and _license_device_id != _envi
|
||||
the_folder = _license_device_id or _environment_device_id or "local-test-device"
|
||||
|
||||
if not the_folder:
|
||||
raise RuntimeError("设备 ID 不能为空")
|
||||
raise RuntimeError("设备 ID 不能为空")
|
||||
|
||||
_DEVICE_TOKEN = None
|
||||
_DEVICE_TOKEN_EXPIRES_AT_MS = 0
|
||||
_DEVICE_TOKEN_LOCK = threading.Lock()
|
||||
|
||||
|
||||
def _current_license_context():
|
||||
payload = get_verified_license() or {}
|
||||
license_id = str(payload.get("license_id") or "").strip()
|
||||
device_id = str(payload.get("device_id") or _environment_device_id or the_folder).strip()
|
||||
return license_id, device_id
|
||||
|
||||
|
||||
def _ensure_device_token(timeout=10):
|
||||
global _DEVICE_TOKEN, _DEVICE_TOKEN_EXPIRES_AT_MS
|
||||
with _DEVICE_TOKEN_LOCK:
|
||||
now_ms = int(time.time() * 1000)
|
||||
if _DEVICE_TOKEN and _DEVICE_TOKEN_EXPIRES_AT_MS - now_ms > 30_000:
|
||||
return _DEVICE_TOKEN
|
||||
|
||||
license_id, device_id = _current_license_context()
|
||||
if not license_id:
|
||||
raise RuntimeError("许可证未就绪,无法获取 deviceToken")
|
||||
|
||||
response = requests.post(device_api_url, json={
|
||||
"type": "deviceAuth",
|
||||
"licenseId": license_id,
|
||||
"deviceId": device_id,
|
||||
}, timeout=timeout)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
if not result.get("success"):
|
||||
raise RuntimeError(result.get("errMsg") or "设备鉴权失败")
|
||||
|
||||
_DEVICE_TOKEN = str(result.get("deviceToken") or "").strip()
|
||||
_DEVICE_TOKEN_EXPIRES_AT_MS = int(result.get("expiresAtMs") or 0)
|
||||
if not _DEVICE_TOKEN or _DEVICE_TOKEN_EXPIRES_AT_MS <= now_ms:
|
||||
raise RuntimeError("设备鉴权返回了无效 deviceToken")
|
||||
return _DEVICE_TOKEN
|
||||
|
||||
|
||||
def device_post(payload, timeout=10):
|
||||
"""Call the device-scoped API route with an auto-renewed device token."""
|
||||
token = _ensure_device_token(timeout=timeout)
|
||||
request_payload = {**payload, "deviceToken": token}
|
||||
response = requests.post(device_api_url, json=request_payload, timeout=timeout)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
if result.get("success"):
|
||||
return result
|
||||
if result.get("errCode") in {"DEVICE_TOKEN_EXPIRED", "DEVICE_TOKEN_INVALID"}:
|
||||
with _DEVICE_TOKEN_LOCK:
|
||||
global _DEVICE_TOKEN, _DEVICE_TOKEN_EXPIRES_AT_MS
|
||||
_DEVICE_TOKEN = None
|
||||
_DEVICE_TOKEN_EXPIRES_AT_MS = 0
|
||||
token = _ensure_device_token(timeout=timeout)
|
||||
response = requests.post(device_api_url, json={**payload, "deviceToken": token}, timeout=timeout)
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
return result
|
||||
Reference in New Issue
Block a user