mirror of
https://github.com/netfun2000/hipudding-teslamate.git
synced 2026-02-27 09:44:28 +08:00
* feat: endpoints by env * fix: typo * fix: useless env * fix: format * fix: distinct auth domain and url * format * fix: force issuer url if needed * feat: new streaming based on vin * fix refresh * revert * up * feat: no need for access token / refresh token if the TOKEN env var is present * feat: update login if token env var exists * feat: add ENV var to allow insecure wss * fix: remove TESLA_CN * fix(naming): TESLA_API_URL to TESLA_API_DOMAIN * feat: add an env var to allo invalid certs on WSS * doc: add API domains env vars description * fix: typo * feat: add env var to change log level * fix: APP_LOG_LEVEL * feat: add TOKEN documention and wording * fix: refacto insecure param * feat: naming and doc * fix: missing env var usage * fix: rebound variable issuer_url * fix: compilation warning on the issuer_url variable * fix: format code * fix: issuer_url assignments * feat: customize polling intervals * typo * update doc * typo * add online interval * add POLLING_ONLINE_INTERVAL * format * add minimum interval * Add minimum on fetch parameter * typo * format * respect immediate fetch, add charging interval * add log level * Respect log_level * format * use LOG_LEVEL env var to facilitate debug * revert on log_level * format * typo * format again * revert on default error intervals * Add a note in MD about polling settings * not let the user set intervals via env variables shorter than our defaults * Fix 401 on direct Fleet API * try to fix in prod context * log test * up * up * format * revert on log * Update refresh.ex --------- Co-authored-by: Julien <julien@citio.digital>
99 lines
2.8 KiB
Elixir
99 lines
2.8 KiB
Elixir
defmodule TeslaApi.Auth do
|
|
use Tesla
|
|
|
|
alias TeslaApi.Error
|
|
|
|
@web_client_id "ownerapi"
|
|
@redirect_uri "https://auth.tesla.com/void/callback"
|
|
|
|
def web_client_id, do: @web_client_id
|
|
def redirect_uri, do: @redirect_uri
|
|
|
|
@default_headers [
|
|
{"user-agent", "TeslaMate/#{Mix.Project.config()[:version]}"},
|
|
{"Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"},
|
|
{"Accept-Language", "en-US,de-DE;q=0.5"}
|
|
]
|
|
|
|
adapter Tesla.Adapter.Finch, name: TeslaMate.HTTP, receive_timeout: 60_000
|
|
|
|
plug TeslaApi.Middleware.FollowRedirects, except: [@redirect_uri]
|
|
plug Tesla.Middleware.BaseUrl, System.get_env("TESLA_AUTH_HOST", "https://auth.tesla.com")
|
|
plug Tesla.Middleware.Headers, @default_headers
|
|
plug Tesla.Middleware.JSON
|
|
plug Tesla.Middleware.Logger, debug: true, log_level: &log_level/1
|
|
|
|
defstruct [:token, :type, :expires_in, :refresh_token, :created_at]
|
|
|
|
defdelegate refresh(auth), to: __MODULE__.Refresh
|
|
|
|
def issuer_url(%__MODULE__{token: access_token}) do
|
|
case derive_issuer_url_from_oat(access_token) do
|
|
{:ok, issuer_url} ->
|
|
issuer_url
|
|
|
|
:error ->
|
|
case decode_jwt_payload(access_token) do
|
|
{:ok, %{"iss" => issuer_url}} -> issuer_url
|
|
_ -> "https://auth.tesla.com/oauth2/v3"
|
|
end
|
|
end
|
|
end
|
|
|
|
def region(%__MODULE__{} = auth) do
|
|
tld =
|
|
auth
|
|
|> issuer_url()
|
|
|> URI.parse()
|
|
|> Map.fetch!(:host)
|
|
|> String.split(".")
|
|
|> List.last()
|
|
|
|
case tld do
|
|
"cn" -> :chinese
|
|
"com" -> :global
|
|
_other -> :other
|
|
end
|
|
end
|
|
|
|
defp derive_issuer_url_from_oat("qts-" <> _),
|
|
do:
|
|
{:ok,
|
|
System.get_env("TESLA_AUTH_HOST", "https://auth.tesla.com") <>
|
|
System.get_env("TESLA_AUTH_PATH", "/oauth2/v3")}
|
|
|
|
defp derive_issuer_url_from_oat("eu-" <> _),
|
|
do:
|
|
{:ok,
|
|
System.get_env("TESLA_AUTH_HOST", "https://auth.tesla.com") <>
|
|
System.get_env("TESLA_AUTH_PATH", "/oauth2/v3")}
|
|
|
|
defp derive_issuer_url_from_oat("cn-" <> _),
|
|
do:
|
|
{:ok,
|
|
System.get_env("TESLA_AUTH_HOST", "https://auth.tesla.com") <>
|
|
System.get_env("TESLA_AUTH_PATH", "/oauth2/v3")}
|
|
|
|
defp derive_issuer_url_from_oat(_), do: :error
|
|
|
|
defp decode_jwt_payload(jwt) do
|
|
with [_algo, payload, _signature] <- String.split(jwt, "."),
|
|
{:ok, payload} <- Base.decode64(payload, padding: false),
|
|
{:ok, payload} <- Jason.decode(payload) do
|
|
{:ok, payload}
|
|
else
|
|
l when is_list(l) ->
|
|
Error.into({:error, :invalid_jwt}, :invalid_access_token)
|
|
|
|
{:error, reason} ->
|
|
Error.into({:error, reason}, :invalid_access_token)
|
|
|
|
_error ->
|
|
Error.into({:error, "Invalid access token"}, :invalid_access_token)
|
|
end
|
|
end
|
|
|
|
defp log_level(%Tesla.Env{} = env) when env.status >= 400, do: :error
|
|
defp log_level(%Tesla.Env{}), do: :info
|
|
end
|