106 lines
2.7 KiB
Elixir
106 lines
2.7 KiB
Elixir
defmodule GeoTherminator.PumpAPI.Auth.Server do
|
|
use GenServer
|
|
import GeoTherminator.TypedStruct
|
|
alias GeoTherminator.PumpAPI.Auth
|
|
require Logger
|
|
|
|
@token_check_timer 10_000
|
|
@token_check_diff 5 * 60
|
|
|
|
defmodule Options do
|
|
deftypedstruct(%{
|
|
server_name: GenServer.name(),
|
|
username: String.t(),
|
|
password: String.t()
|
|
})
|
|
end
|
|
|
|
defmodule State do
|
|
deftypedstruct(%{
|
|
username: String.t(),
|
|
password: String.t(),
|
|
authed_user: {Auth.User.t() | nil, nil},
|
|
installations_fetched: {boolean(), false},
|
|
installations: {[Auth.InstallationInfo.t()], []}
|
|
})
|
|
end
|
|
|
|
@spec start_link(Options.t()) :: GenServer.on_start()
|
|
def start_link(opts) do
|
|
GenServer.start_link(__MODULE__, opts, name: opts.server_name)
|
|
end
|
|
|
|
@impl true
|
|
def init(%Options{} = opts) do
|
|
{:ok, %State{username: opts.username, password: opts.password}, {:continue, :init}}
|
|
end
|
|
|
|
@impl true
|
|
def handle_continue(:init, state) do
|
|
user = Auth.API.auth(state.username, state.password)
|
|
installations = Auth.API.installations_info(user)
|
|
|
|
schedule_token_check()
|
|
|
|
state = %State{
|
|
state
|
|
| authed_user: user,
|
|
installations: installations,
|
|
installations_fetched: true
|
|
}
|
|
|
|
{:noreply, state}
|
|
end
|
|
|
|
@impl true
|
|
def handle_call(msg, from, state)
|
|
|
|
def handle_call(:get_auth, _from, state) do
|
|
{:reply, state.authed_user, state}
|
|
end
|
|
|
|
def handle_call(:get_installations, _from, state) do
|
|
{:reply, state.installations, state}
|
|
end
|
|
|
|
def handle_call({:get_installation, id}, _from, state) do
|
|
{:reply, Enum.find(state.installations, &(&1.id == id)), state}
|
|
end
|
|
|
|
@impl true
|
|
def handle_info(msg, state)
|
|
|
|
def handle_info(:token_check, state) do
|
|
now = DateTime.utc_now()
|
|
diff = DateTime.diff(state.authed_user.token.token_valid_to, now)
|
|
|
|
schedule_token_check()
|
|
|
|
if diff < @token_check_diff do
|
|
Logger.debug("Renewing auth token since #{diff} < #{@token_check_diff}")
|
|
user = Auth.API.auth(state.username, state.password)
|
|
{:noreply, %State{state | authed_user: user}}
|
|
else
|
|
{:noreply, state}
|
|
end
|
|
end
|
|
|
|
@spec get_auth(GenServer.name()) :: Auth.User.t()
|
|
def get_auth(server) do
|
|
GenServer.call(server, :get_auth)
|
|
end
|
|
|
|
@spec get_installations(GenServer.name()) :: Auth.InstallationInfo.t()
|
|
def get_installations(server) do
|
|
GenServer.call(server, :get_installations)
|
|
end
|
|
|
|
@spec get_installation(GenServer.name(), integer()) :: Auth.InstallationInfo.t() | nil
|
|
def get_installation(server, id) do
|
|
GenServer.call(server, {:get_installation, id})
|
|
end
|
|
|
|
defp schedule_token_check() do
|
|
Process.send_after(self(), :token_check, @token_check_timer)
|
|
end
|
|
end
|