Current section
Files
Jump to
Current section
Files
lib/agent/grant.ex
defmodule Dialup.Agent.Grant do
@moduledoc false
@default_ttl :timer.minutes(15)
def new(token, opts \\ %{}) do
opts = Map.new(opts)
now = System.monotonic_time(:millisecond)
ttl = Map.get(opts, :expires_in, @default_ttl)
%{
token: token,
capabilities: normalize_capabilities(Map.get(opts, :capabilities, :all)),
projections: Map.get(opts, :projections, [:state, :regions, :actions]),
require_version: Map.get(opts, :require_version, true),
issued_at: now,
expires_at: if(ttl == :infinity, do: :infinity, else: now + ttl),
revoked_at: nil,
auth_fingerprint: Map.get(opts, :auth_fingerprint, :guest)
}
end
def active?(%{revoked_at: revoked_at}) when not is_nil(revoked_at), do: false
def active?(%{expires_at: :infinity}), do: true
def active?(%{expires_at: expires_at}) do
System.monotonic_time(:millisecond) < expires_at
end
def allows?(grant, capability) do
grant.capabilities == :all or capability in grant.capabilities
end
def projects?(grant, projection), do: projection in grant.projections
def revoke(grant) do
%{grant | revoked_at: System.monotonic_time(:millisecond)}
end
def public(grant) do
%{
"capabilities" =>
if(grant.capabilities == :all,
do: "all",
else: Enum.map(grant.capabilities, &to_string/1)
),
"projections" => Enum.map(grant.projections, &to_string/1),
"requireVersion" => grant.require_version,
"expiresInMs" => remaining_ms(grant)
}
end
defp remaining_ms(%{expires_at: :infinity}), do: nil
defp remaining_ms(%{expires_at: expires_at}) do
max(expires_at - System.monotonic_time(:millisecond), 0)
end
defp normalize_capabilities(:all), do: :all
defp normalize_capabilities(capabilities),
do: capabilities |> List.wrap() |> Enum.map(&normalize/1)
defp normalize(capability) when is_binary(capability), do: capability
defp normalize(capability), do: to_string(capability)
end