Created
July 6, 2017 19:20
-
-
Save erkattak/67a2f10be4b4c117f030caaed77cd420 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule ConnectWeb.Web.Plug.EnsureResourceType do | |
@moduledoc """ | |
This plug ensures that the current_resource's `__struct__` is of the expected type. | |
If one is not found, or is not the expected type, the handler module's `unauthenticated/2` method is called. | |
If a handler is not defined, a `ConnectWeb.Web.Unauthenticated` exception is raised instead. | |
## Example | |
# Will call the unauthenticated/2 function on your handler | |
plug ConnectWeb.Web.Plug.EnsureResourceType, type: %MyStruct{}, handler: MyHandler | |
# Will raise a ConnectWeb.Web.Unauthenticated exception | |
plug ConnectWeb.Web.Plug.EnsureResourceType, type: %MyStruct{} | |
# look in the :secret location | |
plug ConnectWeb.Web.Plug.EnsureResourceType, type: %MyStruct{}, key: :secret | |
If the type option is not passed, no checks will be made against type. | |
""" | |
import Plug.Conn | |
@doc false | |
def init(opts) do | |
opts = Enum.into(opts, %{}) | |
handler = build_handler_tuple(opts) | |
%{ | |
handler: handler, | |
key: Map.get(opts, :key, :default), | |
type: Map.get(opts, :type, :default) | |
} | |
end | |
@doc false | |
def call(conn, opts) do | |
key = Map.get(opts, :key, :default) | |
type = Map.get(opts, :type, :default) | |
case Guardian.Plug.current_resource(conn, key) do | |
nil -> | |
handle_error(conn, opts) | |
res -> | |
check_resource_type(conn, res, type, opts) | |
end | |
end | |
defp check_resource_type(conn, resource, type, opts) do | |
try do | |
case resource.__struct__ do | |
^type -> | |
conn | |
_ -> | |
handle_error(conn, opts) | |
end | |
rescue KeyError -> | |
handle_error(conn, opts) | |
end | |
end | |
defp handle_error(_conn, %{handler: {:default, _}}) do | |
raise ConnectWeb.Web.Unauthenticated, detail: "Invalid subject" | |
end | |
defp handle_error(%Plug.Conn{params: params} = conn, opts) do | |
conn = conn | |
|> assign(:guardian_failure, :unauthenticated) | |
|> halt | |
params = Map.merge(params, %{reason: :unauthenticated}) | |
{mod, meth} = Map.get(opts, :handler) | |
apply(mod, meth, [conn, params]) | |
end | |
defp build_handler_tuple(%{handler: mod}) do | |
{mod, :unauthenticated} | |
end | |
defp build_handler_tuple(_) do | |
{:default, :unauthenticated} | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment