Ich habe eine Phoenix-App, wo ich alle Routen mit Ausnahme der Login-und Benutzererstellungsroute sichern möchte. Um dies zu erreichen, verwende ich die Guardian- und ComeOnIn-Pakete. (Ich habe versucht, this Blog zu folgen)
Ich geschafft, ein Token an den Client in der Sitzungsroute zu senden, und die Erstellung eines Benutzers funktioniert auch.
Aber, wenn ich alle Benutzer anzeigen möchte (dh die Indexroute des Benutzermoduls), erhalte ich einen Authentifizierungsfehler (in meinen Tests habe ich noch nicht die GUI)
Hier ist, was ich getan habe: Benutzer Controller:Failling Authentifizierung
defmodule WarehouseWeb.UserController do
use WarehouseWeb, :controller
alias Warehouse.Account
alias Warehouse.Account.User
action_fallback WarehouseWeb.FallbackController
def index(conn, _params) do
users = Account.list_users()
render(conn, "index.json-api", data: users)
end
# ... ...
end
hier ist die router.ex
defmodule WarehouseWeb.Router do
use WarehouseWeb, :router
pipeline :api do
plug :accepts, ["json", "json-api"]
end
pipeline :api_auth do
plug WarehouseWeb.Guardian.AuthPipeline
end
scope "/api", WarehouseWeb do
pipe_through :api
post "/register", RegistrationController, :create
post "/token", SessionController, :create, as: :login
end
scope "/api", WarehouseWeb do
pipe_through :api_auth
resources "/users", UserController, except: [:new, :edit]
end
end
Und hier sind die notwendigen Module für Guardian:
defmodule WarehouseWeb.Guardian.AuthPipeline do
use Guardian.Plug.Pipeline, otp_app: :warehouse,
module: WarehouseWeb.Guardian,
error_handler: WarehouseWeb.Guardian.AuthErrorHandler
plug Guardian.Plug.VerifyHeader
plug Guardian.Plug.EnsureAuthenticated
end
defmodule Warehouse.Guardian do
use Guardian, otp: :warehouse,
secret_key: "some secret"
def subject_for_token(resource, _claims) do
{:ok, to_string(resource.id)}
end
def resource_from_claims(claims) do
user = Warehouse.Account.get_user!(claims["sub"])
{:ok, user}
end
end
Die Fehlerbehandlung:
defmodule WarehouseWeb.Guardian.AuthErrorHandler do
import Plug.Conn
def auth_error(conn, {type, reason}, opts) do
IO.inspect "authentication is not working!!"
body = Poison.encode!(%{message: to_string(type)})
send_resp(conn, 401, body)
end
end
Und endlich meine Testdatei:
defmodule WarehouseWeb.UserControllerTest do
use WarehouseWeb.ConnCase
alias Warehouse.Account
alias Warehouse.Account.User
@create_attrs %{email: "some email", firstname: "some firstname", lastname: "some lastname", password: "some password"}
@update_attrs %{email: "some updated email", firstname: "some updated firstname", lastname: "some updated lastname", password: "some updated password"}
@invalid_attrs %{email: nil, firstname: nil, lastname: nil, password: nil}
def fixture(:user) do
{:ok, user} = Account.create_user(@create_attrs)
user
end
setup %{conn: conn} do
# create user to be logged in
{:ok, user} = Account.create_user(%{email: "[email protected]", real_password: "abc123", real_password_confirmation: "abc123"})
# create token for session
{:ok, jwt, _claims} = Account.authenticate(%{user: user, password: "abc123"})
# add authorization header to the request
conn = conn
|> put_req_header("authorization", "Bearer: #{jwt}")
|> put_req_header("accept", "application/json")
{:ok, %{conn: conn, user: user}}
end
describe "index" do
test "lists all users", %{conn: conn} do
conn = get conn, user_path(conn, :index)
assert json_response(conn, 200)["data"] == []
end
end
end
Jedesmal, wenn ich meinen Test laufen bekomme ich immer die Fehler Authentifizierung bereits senden, die von meinem Fehler-Handler kommt.
Was fehlt mir, um meinen Test bestehen zu lassen?
EDIT:
Hier ist die Ausgabe:
1) Test Index listet alle Benutzer (WarehouseWeb.UserControllerTest) Test/warehouse_web/controllers/user_controller_test.exs: 32
** (Plug. Conn.AlreadySentError) die Antwort bereits
Code gesendet: conn = get anschl, user_path (conn,: index)
Stacktrace:
(Stecker) lib/Stecker/conn.ex: 508: Plug.Conn.resp/3
(Stecker) lib/Stecker/conn.ex: 495: Plug.Conn.send_resp/3
(Guardian) lib/Wächter/Stecker/ensure_authenticated.ex: 61: Guardian.Plug.EnsureAuthenticated.respond/1
(WarehouseWeb.Guardian.AuthPipeline.plug_builder_call/2
(Lager) lib/warehouse_web/router.ex: 8: WarehouseWeb.Router.api_auth/2
(Lager) lib/warehouse_web/router.ex: 1: anonymous fn/1 in WarehouseWeb.Router. match_route/4
(Phönix) lib/phoenix/router.ex: 273: Phoenix.Router. Anruf/1
(Lager) lib/warehouse_web/endpoint.ex: 1: WarehouseWeb.Endpoint.plug_builder_call/2
(Lager) lib/warehouse_web/endpoint.ex: 1: WarehouseWeb.Endpoint.call/2
(phoenix) lib/phoenix/test/conn_test.ex: 224: Phoenix.ConnTest.dispatch/5
Test/warehouse_web/controllers/user_controller_test.exs: 33: (Test)
Können Sie die vollständige Fehlermeldung mit dem Stacktrace buchen? – Dogbert