Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169defmodule GitSync.Forgejo.OidcTest do use GitSync.DataCase
alias GitSync.Connection alias GitSync.Connections alias GitSync.Forge alias GitSync.Forge.Token alias GitSync.Forgejo.Provider alias GitSync.OidcProvider
setup do issuer = OidcProvider.start(subject: "alice", client_id: "abc")
:ok = Provider.stop() on_exit(&Provider.stop/0)
start_supervised!( {Oidcc.ProviderConfiguration.Worker, %{ issuer: issuer, name: Provider.name(), provider_configuration_opts: %{quirks: %{allow_unsafe_http: true}} }} )
{:ok, connection} = Connections.configure_forgejo(%{ "base_url" => issuer, "client_id" => "abc", "client_secret" => "shh" })
%{connection: connection} end
defp connected(connection, refresh, expires_in) do {:ok, connection} = Connections.record_login( connection, "alice", %{Token.new("forgejo-access-token", refresh, expires_in) | subject: "alice"} )
connection end
test "renews a spent credential against the Forgejo instance", %{connection: connection} do connection = connected(connection, "forgejo-refresh-token", 10)
assert {:ok, %Connection{token: "forgejo-access-token-1"}} = Forge.fresh(connection)
assert %{token: "forgejo-access-token-1", refresh_token: "forgejo-refresh-token-1"} = Connections.forgejo() end
test "a stale snapshot cannot reuse a refresh token", %{connection: connection} do connection = connected(connection, "forgejo-refresh-token", 10)
assert {:ok, current} = Forge.fresh(connection) assert {:ok, ^current} = Forge.fresh(connection) end
test "overlapping consumers share one rotation", %{connection: connection} do connection = connected(connection, "forgejo-refresh-token", 10) supervisor = start_supervised!(Task.Supervisor) OidcProvider.pause_refresh(self())
first = Task.Supervisor.async_nolink(supervisor, fn -> Forge.fresh(connection) end) assert_receive {:refresh_started, provider, ref}, 2000
parent = self()
second = Task.Supervisor.async_nolink(supervisor, fn -> send(parent, :second_started) Forge.fresh(connection) end)
assert_receive :second_started assert Task.yield(second, 100) == nil send(provider, {ref, :continue})
assert {:ok, current} = Task.await(first) assert {:ok, ^current} = Task.await(second) assert current.token == "forgejo-access-token-1" end
test "successive rotations continue from persisted credentials after provider restart", %{ connection: connection } do connection = connected(connection, "forgejo-refresh-token", 10) assert {:ok, first} = Forge.fresh(connection) assert first.token == "forgejo-access-token-1"
{:ok, supervisor} = ExUnit.fetch_test_supervisor() :ok = Supervisor.terminate_child(supervisor, Oidcc.ProviderConfiguration.Worker) {:ok, _worker} = Supervisor.restart_child(supervisor, Oidcc.ProviderConfiguration.Worker)
Connections.forgejo() |> Ecto.Changeset.change(token_expires_at: DateTime.utc_now() |> DateTime.truncate(:second)) |> Repo.update!()
assert {:ok, second} = Forge.fresh(Connections.forgejo()) assert second.token == "forgejo-access-token-2" assert second.refresh_token == "forgejo-refresh-token-2" assert second.subject == "alice" assert DateTime.diff(second.token_expires_at, DateTime.utc_now()) > 3500 end
test "a login during refresh is not overwritten by its response", %{connection: connection} do connection = connected(connection, "forgejo-refresh-token", 10) supervisor = start_supervised!(Task.Supervisor) OidcProvider.pause_refresh(self())
refresh = Task.Supervisor.async_nolink(supervisor, fn -> Forge.fresh(connection) end) assert_receive {:refresh_started, provider, ref}, 2000
login = %{Token.new("login-access", "login-refresh", 3600) | subject: "alice"} assert {:ok, current} = Connections.record_login(connection, "alice", login) send(provider, {ref, :continue})
assert {:ok, ^current} = Task.await(refresh) assert Connections.token(Connections.forgejo()) == login end
test "disconnect during refresh cannot be undone by its response", %{connection: connection} do connection = connected(connection, "forgejo-refresh-token", 10) supervisor = start_supervised!(Task.Supervisor) OidcProvider.pause_refresh(self())
refresh = Task.Supervisor.async_nolink(supervisor, fn -> Forge.fresh(connection) end) assert_receive {:refresh_started, provider, ref}, 2000
assert {:ok, disconnected} = Connections.disconnect(connection) send(provider, {ref, :continue})
assert {:ok, ^disconnected} = Task.await(refresh) assert Connections.token(Connections.forgejo()) == nil assert {:ok, ^disconnected} = Forge.fresh(connection) end
test "a slow refresh does not block another connection", %{connection: connection} do connection = connected(connection, "forgejo-refresh-token", 10) supervisor = start_supervised!(Task.Supervisor) OidcProvider.pause_refresh(self())
refresh = Task.Supervisor.async_nolink(supervisor, fn -> Forge.fresh(connection) end) assert_receive {:refresh_started, provider, ref}, 2000
{:ok, github} = Connections.enable_github(%{"client_id" => "github", "client_secret" => "secret"})
assert {:ok, github} = Connections.store_token(github, Token.new("github-access", nil, 3600)) assert {:ok, ^github} = Forge.fresh(github) send(provider, {ref, :continue})
assert {:ok, %Connection{token: "forgejo-access-token-1"}} = Task.await(refresh) end
test "reports a refresh token the instance no longer honours", %{connection: connection} do connection = connected(connection, "stale", 10)
assert {:error, reason} = Forge.fresh(connection) assert reason =~ "invalid_grant" assert reason =~ "reconnect" assert Connections.forgejo().token == "forgejo-access-token" endend