68 lines
3.1 KiB
Bash
Executable File
68 lines
3.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Jednorázová obnova Tesla refresh tokenu (rotační past: žádné mezikroky).
|
|
# Použití NA SERVERU:
|
|
# 1) otevři authorize URL (vypíše ji tento skript bez argumentů)
|
|
# 2) ./reauth.sh <CODE> — výměna → zápis do DB → ověřovací test
|
|
# Env: CID, CSEC (client id/secret). Redirect URI: https://ems.vojacek.eu/t-auth
|
|
set -euo pipefail
|
|
|
|
REDIRECT="https://ems.vojacek.eu/t-auth"
|
|
AUTH="https://fleet-auth.prd.vn.cloud.tesla.com/oauth2/v3"
|
|
|
|
: "${CID:?export CID='<client_id>'}"
|
|
: "${CSEC:?export CSEC='<client_secret>'}"
|
|
|
|
if [[ $# -lt 1 ]]; then
|
|
echo "Otevři v prohlížeči (consent musí ukázat 'Vehicle location'):"
|
|
echo "$AUTH/authorize?response_type=code&client_id=$CID&redirect_uri=$REDIRECT&scope=openid%20offline_access%20vehicle_device_data%20vehicle_location&state=ems"
|
|
echo
|
|
echo "Pak: $0 <CODE> (do minuty!)"
|
|
exit 0
|
|
fi
|
|
|
|
CODE="$1"
|
|
RESP=$(curl -s "$AUTH/token" \
|
|
-d grant_type=authorization_code \
|
|
--data-urlencode "client_id=$CID" \
|
|
--data-urlencode "client_secret=$CSEC" \
|
|
--data-urlencode "redirect_uri=$REDIRECT" \
|
|
--data-urlencode "code=$CODE")
|
|
|
|
RT=$(echo "$RESP" | python3 -c "import json,sys; print(json.load(sys.stdin).get('refresh_token',''))" 2>/dev/null || true)
|
|
if [[ -z "$RT" ]]; then
|
|
echo "VÝMĚNA SELHALA:"; echo "$RESP"; exit 1
|
|
fi
|
|
|
|
echo "refresh token OK (${#RT} znaků) → DB"
|
|
docker exec -i ems-deploy-db-1 psql -U ems_user -d ems -c \
|
|
"update ems.tesla_token set refresh_token='$RT', access_token=null, access_expires_at=null, updated_at=now() where id=1;"
|
|
|
|
echo "=== ověření ==="
|
|
docker exec -i ems-deploy-backend-1 python - <<'PY'
|
|
import asyncio, asyncpg, os, httpx
|
|
from services.tesla_client import _get_access_token, API_BASE
|
|
async def m():
|
|
c = await asyncpg.connect(host=os.environ["DB_HOST"], port=int(os.environ["DB_PORT"]),
|
|
user=os.environ["DB_USER"], password=os.environ["DB_PASSWORD"], database="ems")
|
|
try:
|
|
tok = await _get_access_token(c)
|
|
if not tok:
|
|
print("REFRESH SELHAL (viz log backendu — po revokaci počkej ~10 min)"); return
|
|
h = {"Authorization": f"Bearer {tok}"}
|
|
async with httpx.AsyncClient(timeout=15, headers=h) as cl:
|
|
r = await cl.get(f"{API_BASE}/api/1/vehicles")
|
|
v = (r.json().get("response") or [None])[0]
|
|
print("vozidlo:", v and v.get("state"))
|
|
if v and v.get("state") == "online":
|
|
r2 = await cl.get(f"{API_BASE}/api/1/vehicles/{v['id']}/vehicle_data",
|
|
params={"endpoints": "location_data"})
|
|
ds = (r2.json().get("response") or {}).get("drive_state") or {}
|
|
print("location scope:", "OK" if ds.get("latitude") is not None
|
|
else f"CHYBI (HTTP {r2.status_code})")
|
|
else:
|
|
print("PRÁZDNÝ SEZNAM vozidel — chybí partner registrace pro tento client_id (docs §3); pozn.: public key hash je vázaný na app — po smazání app nutná rotace klíče (mv private.pem + setup_tesla_domain.sh)") if v is None else print("auto spí — refresh OK, location doověřit po jízdě")
|
|
finally:
|
|
await c.close()
|
|
asyncio.run(m())
|
|
PY
|