Fresh repository history for elektrine/tarakan hosted at https://git.elektrine.com/elektrine/tarakan.
79 lines
3.1 KiB
Elixir
79 lines
3.1 KiB
Elixir
defmodule TarakanWeb.ClientAuthorizationLiveTest do
|
|
use TarakanWeb.ConnCase, async: true
|
|
|
|
import Phoenix.LiveViewTest
|
|
|
|
alias Tarakan.Accounts.ClientAuthorizations
|
|
|
|
setup :register_and_log_in_account
|
|
|
|
test "approve/deny with no loaded authorization flashes instead of crashing", %{conn: conn} do
|
|
# An unknown/expired user code leaves @authorization nil and hides the
|
|
# buttons - but a queued or crafted event must not reach the context with
|
|
# nil and raise a FunctionClauseError.
|
|
{:ok, view, html} = live(conn, ~p"/client/authorize/UNKNOWNXY")
|
|
assert html =~ "invalid or expired"
|
|
|
|
assert render_click(view, "approve") =~ "expired or was already used"
|
|
assert render_click(view, "deny") =~ "expired or was already used"
|
|
end
|
|
|
|
describe "consent screen" do
|
|
test "attributes the client-supplied name instead of asserting it", %{conn: conn} do
|
|
{:ok, _device_code, user_code, _authorization} =
|
|
ClientAuthorizations.start(%{"client_name" => "Totally Official Thing"})
|
|
|
|
{:ok, _view, html} = live(conn, ~p"/client/authorize/#{user_code}")
|
|
|
|
# The name is presented as the request's own claim, next to a warning,
|
|
# rather than as a statement this page vouches for.
|
|
assert html =~ "Calls itself"
|
|
assert html =~ "Totally Official Thing"
|
|
assert html =~ "Nobody at Tarakan will"
|
|
end
|
|
|
|
test "a name carrying control or bidi characters is cleaned before display", %{conn: conn} do
|
|
hostile = "Tarakan" <> "\u202e" <> "lortnoC" <> "\u200b" <> " Client"
|
|
|
|
{:ok, _device_code, user_code, authorization} =
|
|
ClientAuthorizations.start(%{"client_name" => hostile})
|
|
|
|
refute authorization.client_name =~ "\u202e"
|
|
refute authorization.client_name =~ "\u200b"
|
|
|
|
{:ok, _view, html} = live(conn, ~p"/client/authorize/#{user_code}")
|
|
refute html =~ "\u202e"
|
|
end
|
|
|
|
test "a name of only unusable characters falls back to the default", %{conn: _conn} do
|
|
{:ok, _device_code, _user_code, authorization} =
|
|
ClientAuthorizations.start(%{"client_name" => "\u200b\u202e"})
|
|
|
|
assert authorization.client_name == "Tarakan Client"
|
|
end
|
|
|
|
test "a name with markup-shaped characters is refused outright" do
|
|
assert {:error, changeset} =
|
|
ClientAuthorizations.start(%{"client_name" => "Tarakan <script> Client"})
|
|
|
|
assert Keyword.has_key?(changeset.errors, :client_name)
|
|
end
|
|
end
|
|
|
|
describe "user code lookups" do
|
|
test "wrong guesses are budgeted per account", %{conn: conn} do
|
|
# Well past the per-account allowance; the page must stay uninformative
|
|
# rather than answering "exists / does not exist" indefinitely.
|
|
for index <- 1..35 do
|
|
{:ok, _view, html} = live(conn, ~p"/client/authorize/#{"AAAA000" <> to_string(index)}")
|
|
assert html =~ "invalid or expired"
|
|
end
|
|
|
|
# A real code now reads the same as a wrong one: throttled and missing
|
|
# are deliberately indistinguishable.
|
|
{:ok, _device_code, user_code, _authorization} = ClientAuthorizations.start()
|
|
{:ok, _view, html} = live(conn, ~p"/client/authorize/#{user_code}")
|
|
assert html =~ "invalid or expired"
|
|
end
|
|
end
|
|
end
|