95 lines
3.3 KiB
Elixir
95 lines
3.3 KiB
Elixir
defmodule ToweropsWeb.UserCredentialControllerTest do
|
|
use ToweropsWeb.ConnCase, async: true
|
|
|
|
import Towerops.AccountsFixtures
|
|
|
|
alias Towerops.Accounts
|
|
|
|
describe "POST /api/webauthn/registration/challenge" do
|
|
setup :register_and_log_in_user
|
|
|
|
test "returns challenge for authenticated user with confirmed email", %{conn: conn, user: user} do
|
|
conn = post(conn, ~p"/api/webauthn/registration/challenge")
|
|
assert %{"challenge" => challenge, "user" => user_data} = json_response(conn, 200)
|
|
assert is_binary(challenge)
|
|
assert user_data["name"] == user.email
|
|
end
|
|
|
|
test "returns error for user without confirmed email" do
|
|
# Create unconfirmed user
|
|
user = unconfirmed_user_fixture()
|
|
conn = log_in_user(build_conn(), user)
|
|
|
|
conn = post(conn, ~p"/api/webauthn/registration/challenge")
|
|
assert %{"error" => error} = json_response(conn, 403)
|
|
assert error =~ "Email confirmation required"
|
|
end
|
|
|
|
test "requires authentication" do
|
|
conn = build_conn()
|
|
conn = post(conn, ~p"/api/webauthn/registration/challenge")
|
|
assert redirected_to(conn) == ~p"/users/log-in"
|
|
end
|
|
end
|
|
|
|
describe "POST /api/webauthn/authentication/challenge" do
|
|
test "returns challenge for user with passkeys", %{conn: conn} do
|
|
user = user_fixture()
|
|
|
|
# Note: In a real test, we'd create a credential here
|
|
# For now, we test the error path
|
|
conn = post(conn, ~p"/api/webauthn/authentication/challenge", %{"email" => user.email})
|
|
assert %{"error" => _} = json_response(conn, 404)
|
|
end
|
|
|
|
test "returns error for non-existent user", %{conn: conn} do
|
|
conn =
|
|
post(conn, ~p"/api/webauthn/authentication/challenge", %{
|
|
"email" => "nonexistent@example.com"
|
|
})
|
|
|
|
assert %{"error" => _} = json_response(conn, 404)
|
|
end
|
|
|
|
test "does not require authentication", %{conn: conn} do
|
|
user = user_fixture()
|
|
conn = post(conn, ~p"/api/webauthn/authentication/challenge", %{"email" => user.email})
|
|
# Should not redirect to login
|
|
assert conn.status in [200, 404]
|
|
end
|
|
end
|
|
|
|
describe "DELETE /users/credentials/:id" do
|
|
setup :register_and_log_in_user
|
|
|
|
test "deletes credential successfully", %{conn: conn, user: user} do
|
|
# Create a test credential
|
|
credential = credential_fixture(user, %{name: "Test Key"})
|
|
|
|
conn = delete(conn, ~p"/users/credentials/#{credential.id}")
|
|
assert redirected_to(conn) == ~p"/users/settings"
|
|
assert Phoenix.Flash.get(conn.assigns.flash, :info) =~ "deleted successfully"
|
|
|
|
# Verify credential is deleted
|
|
assert Accounts.list_user_credentials(user.id) == []
|
|
end
|
|
|
|
test "cannot delete another user's credential", %{conn: conn} do
|
|
other_user = user_fixture()
|
|
credential = credential_fixture(other_user, %{name: "Other Key"})
|
|
|
|
conn = delete(conn, ~p"/users/credentials/#{credential.id}")
|
|
assert redirected_to(conn) == ~p"/users/settings"
|
|
assert Phoenix.Flash.get(conn.assigns.flash, :error) =~ "not found"
|
|
|
|
# Verify credential still exists
|
|
assert length(Accounts.list_user_credentials(other_user.id)) == 1
|
|
end
|
|
|
|
test "requires authentication" do
|
|
conn = build_conn()
|
|
conn = delete(conn, ~p"/users/credentials/#{Ecto.UUID.generate()}")
|
|
assert redirected_to(conn) == ~p"/users/log-in"
|
|
end
|
|
end
|
|
end
|