私は自分のものでないAPIリソースをユーザーが要求できないようにプラグを開発しようとしています。たとえば、JohnがAlexのプロフィールを更新しようとすると、そのリソースは彼のプロフィールではないので、アプリケーションは不正なエラーを投げます。私はGuardianを認証に使用していますが、それを忘れていない限り、GuardianのドキュメントはAPIを提供していません。だから私は自分でプラグを作成すると思った。カスタムエリクシールユーザーが自分以外のAPIリソースを要求しないようにするためのプラグ
しかし、私の実装では、カスタムプラグインを適用した(またはむしろ「パイプした」)すべての要求を拒否しているようです。
defmodule ExampleApp.Authorization do
use ExampleApp.Web, :controller
def init(opts \\ nil), do: opts
def call(conn, _opts) do
case Guardian.Plug.current_resource(conn) do
nil ->
conn
|> put_status(:unauthorized)
|> render(ExampleApp.SessionView, "forbidden.json", error: "Not Authorized")
|> halt
user ->
if user.id == conn.params["id"] do
conn
else
conn
|> put_status(:unauthorized)
|> render(ExampleApp.SessionView, "forbidden.json", error: "Not Authorized")
|> halt
end
end
end
end
だから私はconn.params["id"]
にuser.id
を比較するために、いくつかのコンソールの印刷を行ってきたとの比較は、ユーザID が要求したユーザーのIDでテストケースのために真である:以下のプラグインを参照してください。しかし、if-elseステートメントの 'else'条件が実行されているようです。かなり混乱しています。ここで
は
test "valid UPDATE of user at /users/:id route", %{conn: conn, id: id} do
conn = put conn, user_path(conn, :update, id), user: %{first_name: "bob"}
assert json_response(conn, 200)["first_name"] == "bob"
end
test "valid DELETE of user at /users/:id route", %{conn: conn, id: id} do
conn = delete conn, user_path(conn, :delete, id)
assert json_response(conn, 200)
refute Repo.get(User, id)
end
を失敗している2つのテストは、しかし、これらのエラーは、このエラーに基づいて
** (RuntimeError) expected response with status 200, got: 401, with body:
{"error":"Not Authorized"}
の両方のためにスローされている、上からプラグインは「他」の条件を実行しています。ここで
がUserControllerで
あるdefmodule ExampleApp.UserController do
use ExampleApp.Web, :controller
plug Guardian.Plug.EnsureAuthenticated, handler: ExampleApp.SessionController
plug ExampleApp.Authorization when action in [:update, :delete] # Plug only runs for update and delete actions
alias ExampleApp.{Repo, User, SessionView}
#....
def update(conn, %{"id" => id}) do
body = conn.params["user"]
changeset =
User
|> Repo.get!(id)
|> User.edit_changeset(body)
case Repo.update(changeset) do
{:ok, updated_user} ->
conn
|> put_status(:ok)
|> render(SessionView, "show.json", %{user: updated_user})
{:error, _ } ->
conn
|> put_status(:bad_request)
|> render(SessionView, "error.json", %{error: "User could not be persisted to DB"})
end
end
def delete(conn, %{"id" => id}) do
user = Repo.get!(User, id)
case Repo.delete(user) do
{:ok, _} ->
conn
|> put_status(:ok)
|> render(SessionView, "delete.json")
{:error, _} ->
conn
|> put_status(:bad_request)
|> render(SessionView, "error.json")
end
end
end
だから私はそれが私のプラグインの実装に関係しているという結論に来ています。私は間違っているかもしれませんが、私のコードを見てみたいと思います。認証され、許可された要求が拒否されるテストケースはなぜですか?
'user.id'は整数ですか?これは動作しますか? 'Integer.to_string(user.id)== conn.params [" id "] do'? – Dogbert
@Dogbert Manそれは常に最小のものです。迅速で有益な回答をいただきありがとうございます。あなたの男の小道具。 –