Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
3.3 kB · 103 lines
Elixir
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104defmodule TrackerWeb.ApiTokenIntegrationTest do use TrackerWeb.ConnCase, async: true
alias Tracker.Accounts.{ApiToken, User} alias TrackerWeb.Plug.{BearerAuth, RequireRole}
describe "full bearer auth flow" do test "admin creates a service account, issues a token, and a request guarded by BearerAuth+RequireRole succeeds" do admin = register_via_github!() |> grant_admin!() service = User.create_service_account!("ingest", [:user, :admin], actor: admin) {:ok, %{token: jwt}} = ApiToken.issue(service.id, %{label: "robot"}, actor: admin)
conn = call_guarded(jwt, :admin)
refute conn.halted assert conn.assigns.current_user.id == service.id assert User.has_role?(conn.assigns.current_user, :admin) end
test "missing header is rejected with 401 by the bearer auth plug" do conn = call_guarded(nil, :admin)
assert conn.halted assert conn.status == 401 end
test "revoked token is rejected with 401" do admin = register_via_github!() |> grant_admin!() service = User.create_service_account!("ingest", [:user, :admin], actor: admin) {:ok, %{token: jwt, jti: jti}} = ApiToken.issue(service.id, %{}, actor: admin) {:ok, _} = ApiToken.revoke(jti, actor: admin)
conn = call_guarded(jwt, :admin)
assert conn.halted assert conn.status == 401 end
test "token whose user lacks the required role is rejected with 403" do admin = register_via_github!() |> grant_admin!() service = User.create_service_account!("plain", [:user], actor: admin) {:ok, %{token: jwt}} = ApiToken.issue(service.id, %{}, actor: admin)
conn = call_guarded(jwt, :admin)
assert conn.halted assert conn.status == 403 end
test "non-admin attempting to issue a token for another user is rejected" do alice = register_via_github!() bob = register_via_github!()
assert {:error, %Ash.Error.Forbidden{}} = ApiToken.issue(bob.id, %{}, actor: alice) end end
defp call_guarded(jwt, required_role) do build_conn(:get, "/") |> maybe_put_bearer(jwt) |> BearerAuth.call(BearerAuth.init([])) |> require_role_if_alive(required_role) end
defp maybe_put_bearer(conn, nil), do: conn defp maybe_put_bearer(conn, jwt), do: put_req_header(conn, "authorization", "Bearer " <> jwt)
defp require_role_if_alive(%{halted: true} = conn, _role), do: conn
defp require_role_if_alive(conn, role), do: RequireRole.call(conn, RequireRole.init(role: role))
defp register_via_github!(overrides \\ %{}) do user_info = Map.merge( %{ "id" => System.unique_integer([:positive]), "login" => "user_#{System.unique_integer([:positive])}" }, overrides )
User |> Ash.Changeset.for_create(:register_with_github, user_info: user_info, oauth_tokens: %{"access_token" => "tok"} ) |> Ash.create!(authorize?: false) end
defp grant_admin!(%User{} = user) do import Ecto.Query
Tracker.Repo.update_all( from(u in "users", where: u.github_id == ^user.github_id), set: [roles: ["user", "admin"]] )
refreshed = Ash.get!(User, user.id, authorize?: false) %{refreshed | __metadata__: user.__metadata__} endend