Skip to content

Instantly share code, notes, and snippets.

@erkattak
Created July 6, 2017 19:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erkattak/67a2f10be4b4c117f030caaed77cd420 to your computer and use it in GitHub Desktop.
Save erkattak/67a2f10be4b4c117f030caaed77cd420 to your computer and use it in GitHub Desktop.
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