Packages

Elixir SDK for the Hallpass agent identity and message proof protocol.

Current section

Files

Jump to
hallpass_sdk lib hallpass_sdk client.ex
Raw

lib/hallpass_sdk/client.ex

defmodule HallpassSdk.Client do
@moduledoc """
HTTP client for the Hallpass API.
Uses `Req` for HTTP transport. All functions accept an optional base URL
(defaults to `https://hallpass.org`).
## Usage
client = HallpassSdk.Client.new()
{:ok, profile} = HallpassSdk.Client.get_public_profile(client, "alice")
"""
@type t :: %__MODULE__{base_url: String.t(), session_cookie: String.t() | nil}
defstruct base_url: HallpassSdk.default_base_url(), session_cookie: nil
@spec new(keyword()) :: t()
def new(opts \\ []) do
%__MODULE__{
base_url: Keyword.get(opts, :base_url, HallpassSdk.default_base_url()),
session_cookie: Keyword.get(opts, :session_cookie)
}
end
@spec get_public_profile(t(), String.t()) :: {:ok, map()} | {:error, term()}
def get_public_profile(%__MODULE__{} = client, username) do
get(client, "/api/v1/profiles/#{username}")
end
@spec create_message(t(), map()) :: {:ok, map()} | {:error, term()}
def create_message(%__MODULE__{} = client, bundle) do
post(client, "/api/v1/messages", %{bundle: bundle})
end
@spec verify_message(t(), map()) :: {:ok, map()} | {:error, term()}
def verify_message(%__MODULE__{} = client, bundle) do
post(client, "/api/v1/verify/message", %{bundle: bundle})
end
@spec get_message_verification(t(), String.t()) :: {:ok, map()} | {:error, term()}
def get_message_verification(%__MODULE__{} = client, message_id) do
get(client, "/api/v1/messages/#{message_id}/verification")
end
@spec register_agent(t(), map()) :: {:ok, map()} | {:error, term()}
def register_agent(%__MODULE__{} = client, params) do
post(client, "/api/v1/auth/agents", params)
end
@spec issue_challenge(t(), String.t()) :: {:ok, map()} | {:error, term()}
def issue_challenge(%__MODULE__{} = client, agent_id) do
post(client, "/api/v1/auth/agents/#{agent_id}/challenge", %{})
end
@spec verify_challenge(t(), String.t(), String.t()) :: {:ok, map()} | {:error, term()}
def verify_challenge(%__MODULE__{} = client, agent_id, challenge_jwt) do
post(client, "/api/v1/auth/agents/#{agent_id}/challenge/verify", %{
challenge_jwt: challenge_jwt
})
end
@spec create_delegation(t(), map()) :: {:ok, map()} | {:error, term()}
def create_delegation(%__MODULE__{} = client, params) do
post(client, "/api/v1/auth/delegations", params)
end
defp get(%__MODULE__{} = client, path) do
url = String.trim_trailing(client.base_url, "/") <> path
case Req.get(url, headers: headers(client)) do
{:ok, %Req.Response{status: status, body: body}} when status in 200..299 ->
{:ok, body}
{:ok, %Req.Response{status: status, body: body}} ->
{:error, {status, body}}
{:error, reason} ->
{:error, reason}
end
end
defp post(%__MODULE__{} = client, path, body) do
url = String.trim_trailing(client.base_url, "/") <> path
case Req.post(url, json: body, headers: headers(client)) do
{:ok, %Req.Response{status: status, body: resp_body}} when status in 200..299 ->
{:ok, resp_body}
{:ok, %Req.Response{status: status, body: resp_body}} ->
{:error, {status, resp_body}}
{:error, reason} ->
{:error, reason}
end
end
defp headers(%__MODULE__{session_cookie: nil}), do: []
defp headers(%__MODULE__{session_cookie: cookie}) do
[{"cookie", "_hallpass_session=#{cookie}"}]
end
end