defmodule HostasWeb.Auth.TokenControllerTest do use HostasWeb.ConnCase # For testing with Ecto import Ecto.Query, only: [from: 2] alias Hostas.Repo alias Hostas.Denizen alias Hostas.Token defp create_denizen(handle \\ "denizen") do Repo.insert!( Denizen.changeset(%Denizen{}, %{handle: handle, name: "Test Denizen", password: "password"}) ) end describe "token create" do test "creates a token", %{conn: conn} do create_denizen() conn = post(conn, ~p"/hostapi/auth/token", %{handle: "denizen", password: "password"}) assert Map.has_key?(json_response(conn, 201), "token") assert Map.has_key?(json_response(conn, 201), "expires") end test "fails due to password mismatch", %{conn: conn} do create_denizen() conn = post(conn, ~p"/hostapi/auth/token", %{handle: "denizen", password: "incorrect"}) assert json_response(conn, 401)["error"] == "Password mismatch" end test "fails due to non-existant denizen", %{conn: conn} do conn = post(conn, ~p"/hostapi/auth/token", %{handle: "denizen", password: "password"}) assert json_response(conn, 404)["error"] == "No user with handle denizen" end test "fails due to missing fields", %{conn: conn} do conn = post(conn, ~p"/hostapi/auth/token", %{password: "password"}) assert json_response(conn, 422)["error"] == "Missing required parameters" end end describe "token verification" do test "succeeds", %{conn: conn} do {:ok, struct} = Token.new(create_denizen().id) conn = conn |> put_req_header("authorization", "Bearer #{struct.token}") |> get(~p"/hostapi/auth/token") assert Map.has_key?(json_response(conn, 200), "expires") end test "fails because of expiry", %{conn: conn} do {:ok, struct} = Token.new(create_denizen().id, -10) conn = conn |> put_req_header("authorization", "Bearer #{struct.token}") |> get(~p"/hostapi/auth/token") assert json_response(conn, 401)["error"] == "Token expired" end test "fails because of unrecognized credentials", %{conn: conn} do conn = conn |> put_req_header("authorization", "Bearer unknown_credential") |> get(~p"/hostapi/auth/token") assert json_response(conn, 401)["error"] == "API key not found" end end describe "token revocation" do test "succeeds", %{conn: conn} do {:ok, struct} = Token.new(create_denizen().id) conn = conn |> put_req_header("authorization", "Bearer #{struct.token}") |> delete(~p"/hostapi/auth/token/#{struct.id}") assert response(conn, 200) end test "fails because it's someone else's token", %{conn: conn} do {:ok, struct1} = Token.new(create_denizen("denizen1").id) {:ok, struct2} = Token.new(create_denizen("denizen2").id) conn = conn |> put_req_header("authorization", "Bearer #{struct1.token}") |> delete(~p"/hostapi/auth/token/#{struct2.id}") assert json_response(conn, 404)["error"] == "Token not found" end test "fails because the token doesn't exist", %{conn: conn} do {:ok, struct} = Token.new(create_denizen().id) conn = conn |> put_req_header("authorization", "Bearer #{struct.token}") |> delete(~p"/hostapi/auth/token/#{struct.id + 1}") assert json_response(conn, 404)["error"] == "Token not found" end end describe "token renewal" do test "succeeds", %{conn: conn} do {:ok, struct} = Token.new(create_denizen().id) conn = conn |> put_req_header("authorization", "Bearer #{struct.token}") |> get(~p"/hostapi/auth/token/${struct.id}/renew") assert Map.has_key?(json_response(conn, 200), "token") assert Map.has_key?(json_response(conn, 200), "expires") assert not Repo.exists?(from t in Token, where: t.id == ^struct.id) end test "fails because it's not the user's token", %{conn: conn} do {:ok, struct1} = Token.new(create_denizen("denizen1").id) {:ok, struct2} = Token.new(create_denizen("denizen2").id) conn = conn |> put_req_header("authorization", "Bearer #{struct1.token}") |> get(~p"/hostapi/auth/token/#{struct2.id}/renew") assert json_response(conn, 404)["error"] == "Token not found" assert Repo.exists?(from t in Token, where: t.id == ^struct2.id) end test "fails because it doesn't exist", %{conn: conn} do {:ok, struct} = Token.new(create_denizen().id) conn = conn |> put_req_header("authorization", "Bearer #{struct.token}") |> get(~p"/hostapi/auth/token/#{struct.id + 1}/renew") assert json_response(conn, 404)["error"] == "Token not found" assert Repo.exists?(from t in Token, where: t.id == ^struct.id) end end end