Skip to content

Commit

Permalink
feat: sign_in_anonymously/2 (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
zoedsoupe authored Feb 15, 2025
1 parent 2b86a1e commit f4f16dd
Show file tree
Hide file tree
Showing 7 changed files with 127 additions and 5 deletions.
22 changes: 21 additions & 1 deletion lib/supabase/go_true.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ defmodule Supabase.GoTrue do
alias Supabase.GoTrue.Schemas.ResendParams
alias Supabase.GoTrue.Schemas.ServerHealth
alias Supabase.GoTrue.Schemas.ServerSettings
alias Supabase.GoTrue.Schemas.SignInAnonymously
alias Supabase.GoTrue.Schemas.SignInWithIdToken
alias Supabase.GoTrue.Schemas.SignInWithOauth
alias Supabase.GoTrue.Schemas.SignInWithOTP
Expand Down Expand Up @@ -157,12 +158,31 @@ defmodule Supabase.GoTrue do
"""
@impl true
def sign_in_with_password(%Client{} = client, credentials) do
with {:ok, credentials} <- SignInWithPassword.parse(credentials),
with {:ok, credentials} <- SignInWithPassword.parse(Map.new(credentials)),
{:ok, response} <- UserHandler.sign_in_with_password(client, credentials) do
Session.parse(response.body)
end
end

@doc """
Signs in a user anonymously.
## Parameters
- `client` - The `Supabase` client to use for the request.
- `opts` - The options to use for the sign in. Check `Supabase.GoTrue.Schemas.SignInAnonymously` for more information.
## Examples
iex> Supabase.GoTrue.sign_in_anonymously(pid | client_name, %{})
{:ok, %Supabase.GoTrue.Session{}}
"""
@spec sign_in_anonymously(Client.t(), Enumerable.t()) :: {:ok, Session.t()} | {:error, term}
def sign_in_anonymously(%Client{} = client, opts \\ %{}) do
with {:ok, params} <- SignInAnonymously.parse(Map.new(opts)),
{:ok, resp} <- UserHandler.sign_in_anonymously(client, params) do
Session.parse(resp.body)
end
end

@doc """
Signs up a user with email/phone and password.
Expand Down
31 changes: 31 additions & 0 deletions lib/supabase/go_true/schemas/sign_in_anonymously.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
defmodule Supabase.GoTrue.Schemas.SignInAnonymously do
@moduledoc """
This schema is used to validate and parse the parameters for signing in anonymously.
"""

use Ecto.Schema

import Ecto.Changeset

@type t :: %__MODULE__{
data: map | nil,
captcha_token: String.t() | nil
}

@derive Jason.Encoder
@primary_key false
embedded_schema do
field(:data, :map)
field(:captcha_token, :string)
end

def to_sign_in_params(%__MODULE__{} = signin) do
Map.take(signin, [:data])
end

def parse(source \\ %__MODULE__{}, %{} = attrs) do
source
|> cast(attrs, [:data, :captcha_token])
|> apply_action(:insert)
end
end
5 changes: 3 additions & 2 deletions lib/supabase/go_true/session.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ defmodule Supabase.GoTrue.Session do
access_token: String.t(),
refresh_token: String.t(),
expires_in: integer,
expires_at: NaiveDateTime.t() | nil,
# unix timestamp
expires_at: integer | nil,
token_type: String.t(),
user: User.t()
}
Expand All @@ -41,7 +42,7 @@ defmodule Supabase.GoTrue.Session do
field(:access_token, :string)
field(:refresh_token, :string)
field(:expires_in, :integer)
field(:expires_at, :utc_datetime)
field(:expires_at, :integer)
field(:token_type, :string)

embeds_one(:user, User)
Expand Down
2 changes: 1 addition & 1 deletion lib/supabase/go_true/user.ex
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ defmodule Supabase.GoTrue.User do
user
|> cast(attrs, @required_fields ++ @optional_fields)
|> validate_required(@required_fields)
|> cast_embed(:identities, required: true)
|> cast_embed(:identities, required: false)
|> cast_embed(:factors, required: false)
end

Expand Down
9 changes: 9 additions & 0 deletions lib/supabase/go_true/user_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ defmodule Supabase.GoTrue.UserHandler do
alias Supabase.GoTrue
alias Supabase.GoTrue.PKCE
alias Supabase.GoTrue.Schemas.ResendParams
alias Supabase.GoTrue.Schemas.SignInAnonymously
alias Supabase.GoTrue.Schemas.SignInRequest
alias Supabase.GoTrue.Schemas.SignInWithIdToken
alias Supabase.GoTrue.Schemas.SignInWithOauth
Expand Down Expand Up @@ -120,6 +121,14 @@ defmodule Supabase.GoTrue.UserHandler do
end
end

def sign_in_anonymously(%Client{} = client, %SignInAnonymously{} = opts) do
client
|> GoTrue.Request.base(@sign_up_uri)
|> Request.with_method(:post)
|> Request.with_body(%{"options" => opts})
|> Fetcher.request()
end

@grant_types ~w[password id_token]

def sign_in_with_password(%Client{} = client, %SignInWithPassword{} = signin) do
Expand Down
61 changes: 61 additions & 0 deletions test/supabase/go_true_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,67 @@ defmodule Supabase.GoTrueTest do
end
end

describe "sign_in_anonymously/2" do
test "successfully signs in an user anonymously", %{client: client} do
data = %{captcha_token: "123"}

@mock
|> expect(:request, fn %Request{} = req, _opts ->
assert req.method == :post
assert req.url.path =~ "/signup"

assert %{
"options" => %{"captcha_token" => "123"}
} = Jason.decode!(req.body)

user = user_fixture(id: "123", identities: []) |> Map.from_struct()
body = session_fixture_json(access_token: "123", user: user)

{:ok, %Finch.Response{status: 201, body: body, headers: []}}
end)

assert {:ok, %Session{} = session} = GoTrue.sign_in_anonymously(client, data)
assert session.access_token == "123"
assert session.user.id == "123"
end

test "returns an error on unexpected error", %{client: client} do
data = %{captcha_token: "123"}

@mock
|> expect(:request, fn %Request{} = req, _opts ->
assert req.method == :post
assert req.url.path =~ "/signup"

assert %{
"options" => %{"captcha_token" => "123"}
} = Jason.decode!(req.body)

{:error, %Mint.TransportError{reason: :timeout}}
end)

assert {:error, %Supabase.Error{}} = GoTrue.sign_in_anonymously(client, data)
end

test "returns an error on authentication error", %{client: client} do
data = %{captcha_token: "123"}

@mock
|> expect(:request, fn %Request{} = req, _opts ->
assert req.method == :post
assert req.url.path =~ "/signup"

assert %{
"options" => %{"captcha_token" => "123"}
} = Jason.decode!(req.body)

{:ok, %Finch.Response{status: 401, body: "{}", headers: []}}
end)

assert {:error, %Supabase.Error{}} = GoTrue.sign_in_anonymously(client, data)
end
end

describe "sign_up/2" do
test "successfully signs up an user with email and password", %{client: client} do
data = %{
Expand Down
2 changes: 1 addition & 1 deletion test/support/fixtures/session_fixture.ex
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ defmodule Supabase.GoTrue.SessionFixture do
access_token: "111",
refresh_token: "111",
expires_in: 3600,
expires_at: ~U[2024-01-01 00:00:00.0Z],
expires_at: 1_000_000_000,
token_type: "bearer",
user: UserFixture.user_fixture(attrs[:user] || %{})
}
Expand Down

0 comments on commit f4f16dd

Please sign in to comment.