Skip to content
This repository has been archived by the owner on Apr 3, 2024. It is now read-only.

Handle not found with required #83

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,33 @@
language: elixir
elixir:
- 1.8
- 1.7
- 1.6
- 1.5
- 1.4
- 1.3

otp_release:
- 20.0
- 21.1
- 20.3
- 19.3
- 18.3

matrix:
exclude:
- elixir: 1.8
otp_release: 19.3
- elixir: 1.8
otp_release: 18.3
- elixir: 1.7
otp_release: 18.3
- elixir: 1.6
otp_release: 18.3
- elixir: 1.5
otp_release: 21.1
- elixir: 1.4
otp_release: 21.1
- elixir: 1.3
otp_release: 20.0
otp_release: 21.1
- elixir: 1.3
otp_release: 20.3
script: mix test && mix credo
10 changes: 8 additions & 2 deletions lib/canary/plugs.ex
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ defmodule Canary.Plugs do
* `:id_field` - Specifies the name of the ID field in the database for searching :id_name value, defaults to "id".
* `:persisted` - Specifies the resource should always be loaded from the database, defaults to false
* `:not_found_handler` - Specify a handler function to be called if the resource is not found
* `:required` - Same as `:persisted` but with not found handler - even for :index, :new or :create action

Examples:
```
Expand Down Expand Up @@ -438,7 +439,11 @@ defmodule Canary.Plugs do
end

defp persisted?(opts) do
!!Keyword.get(opts, :persisted, false)
!!Keyword.get(opts, :persisted, false) || !!Keyword.get(opts, :required, false)
end

defp required?(opts) do
!!Keyword.get(opts, :required, false)
end

defp get_resource_name(conn, opts) do
Expand Down Expand Up @@ -494,9 +499,10 @@ defmodule Canary.Plugs do
else
[:index, :new, :create]
end
is_required = required?(opts)
resource_name = Map.get(conn.assigns, get_resource_name(conn, opts))

if is_nil(resource_name) and not action in non_id_actions do
if is_nil(resource_name) and (is_required or not(action in non_id_actions)) do
apply_error_handler(conn, :not_found_handler, opts)
else
conn
Expand Down
3 changes: 1 addition & 2 deletions mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ defmodule Canary.Mixfile do
{:ex_doc, "~> 0.7", only: :dev},
{:earmark, ">= 0.0.0", only: :dev},
{:mock, ">= 0.0.0", only: :test},

{:credo, "~> 0.5", only: [:dev, :test]}
{:credo, "~> 1.0", only: [:dev, :test]}
]
end
end
13 changes: 8 additions & 5 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
%{"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], []},
%{
"bunt": {:hex, :bunt, "0.2.0", "951c6e801e8b1d2cbe58ebbd3e616a869061ddadcc4863d0a2182541acae9a38", [:mix], []},
"canada": {:hex, :canada, "1.0.1", "da96d0ff101a0c2a6cc7b07d92b8884ff6508f058781d3679999416feacf41c5", [:mix], []},
"credo": {:hex, :credo, "0.6.1", "a941e2591bd2bd2055dc92b810c174650b40b8290459c89a835af9d59ac4a5f8", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, optional: false]}]},
"decimal": {:hex, :decimal, "1.1.2", "79a769d4657b2d537b51ef3c02d29ab7141d2b486b516c109642d453ee08e00c", [:mix], []},
"credo": {:hex, :credo, "1.1.5", "caec7a3cadd2e58609d7ee25b3931b129e739e070539ad1a0cd7efeeb47014f4", [:mix], [{:bunt, "~> 0.2.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm"},
"decimal": {:hex, :decimal, "1.8.0", "ca462e0d885f09a1c5a342dbd7c1dcf27ea63548c65a65e67334f4b61803822e", [:mix], [], "hexpm"},
"earmark": {:hex, :earmark, "0.2.1", "ba6d26ceb16106d069b289df66751734802777a3cbb6787026dd800ffeb850f3", [:mix], []},
"ecto": {:hex, :ecto, "2.0.2", "b02331c1f20bbe944dbd33c8ecd8f1ccffecc02e344c4471a891baf3a25f5406", [:mix], [{:db_connection, "~> 1.0-rc.2", [hex: :db_connection, optional: true]}, {:decimal, "~> 1.0", [hex: :decimal, optional: false]}, {:mariaex, "~> 0.7.7", [hex: :mariaex, optional: true]}, {:poison, "~> 1.5 or ~> 2.0", [hex: :poison, optional: true]}, {:poolboy, "~> 1.5", [hex: :poolboy, optional: false]}, {:postgrex, "~> 0.11.2", [hex: :postgrex, optional: true]}, {:sbroker, "~> 1.0-beta", [hex: :sbroker, optional: true]}]},
"ex_doc": {:hex, :ex_doc, "0.11.5", "0dc51cb84f8312162a2313d6c71573a9afa332333d8a332bb12540861b9834db", [:mix], [{:earmark, "~> 0.1.17 or ~> 0.2", [hex: :earmark, optional: true]}]},
"meck": {:hex, :meck, "0.8.4", "59ca1cd971372aa223138efcf9b29475bde299e1953046a0c727184790ab1520", [:make, :rebar], []},
"jason": {:hex, :jason, "1.1.2", "b03dedea67a99223a2eaf9f1264ce37154564de899fd3d8b9a21b1a6fd64afe7", [:mix], [{:decimal, "~> 1.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm"},
"meck": {:hex, :meck, "0.8.13", "ffedb39f99b0b99703b8601c6f17c7f76313ee12de6b646e671e3188401f7866", [:rebar3], [], "hexpm"},
"mock": {:hex, :mock, "0.1.3", "657937b03f88fce89b3f7d6becc9f1ec1ac19c71081aeb32117db9bc4d9b3980", [:mix], [{:meck, "~> 0.8.2", [hex: :meck, optional: false]}]},
"plug": {:hex, :plug, "1.1.5", "de5645c18170415a72b18cc3d215c05321ddecac27a15acb923742156e98278b", [:mix], [{:cowboy, "~> 1.0", [hex: :cowboy, optional: true]}]},
"poolboy": {:hex, :poolboy, "1.5.1", "6b46163901cfd0a1b43d692657ed9d7e599853b3b21b95ae5ae0a777cf9b6ca8", [:rebar], []}}
"poolboy": {:hex, :poolboy, "1.5.1", "6b46163901cfd0a1b43d692657ed9d7e599853b3b21b95ae5ae0a777cf9b6ca8", [:rebar], []},
}
35 changes: 34 additions & 1 deletion test/plug_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,39 @@ defmodule PlugTest do
assert load_resource(conn, opts) == expected
end

test "it calls the specified action when not_found with opts[:required] specified on :new action" do
opts = [model: Post, not_found_handler: {Helpers, :not_found_handler}, required: true]

params = %{"id" => 3}
conn = conn(%Plug.Conn{assigns: %{post: nil}, private: %{phoenix_action: :new}}, :get, "/posts/3/new", params)

expected = Helpers.not_found_handler(conn)

assert load_resource(conn, opts) == expected
end

test "it calls the specified action when not_found with opts[:required] specified on :create action" do
opts = [model: Post, not_found_handler: {Helpers, :not_found_handler}, required: true]

params = %{"id" => 3}
conn = conn(%Plug.Conn{assigns: %{post: nil}, private: %{phoenix_action: :index}}, :post, "/posts/3/new", params)

expected = Helpers.not_found_handler(conn)

assert load_resource(conn, opts) == expected
end

test "it calls the specified action when not_found with opts[:required] specified on :index action" do
opts = [model: Post, not_found_handler: {Helpers, :not_found_handler}, required: true]

params = %{"id" => 3}
conn = conn(%Plug.Conn{assigns: %{post: nil}, private: %{phoenix_action: :index}}, :get, "/posts/3", params)

expected = Helpers.not_found_handler(conn)

assert load_resource(conn, opts) == expected
end

test "it authorizes the resource correctly" do
opts = [model: Post]

Expand Down Expand Up @@ -1529,7 +1562,7 @@ defmodule PlugTest do
params
)

assert_raise Protocol.UndefinedError, "protocol Enumerable not implemented for :other_action", fn->
assert_raise Protocol.UndefinedError, ~r/protocol Enumerable not implemented for :other_action/, fn->
authorize_resource(conn, opts)
end
end
Expand Down