2017-04-20 31 views
0

我在我的鳳凰應用中使用canary libphoenix canary not_found handler

我config.exs寫道:

config :canary, repo: MyApp.Repo, 
     unauthorized_handler: {MyApp.Helpers, :handle_unauthorized}, 
     not_found_handler: {MyApp.Helpers, :handle_not_found} 

,創造了幫手:

defmodule MyApp.Helpers do 
    use Phoenix.Controller 

    require Logger 
    import Plug.Conn 

    def handle_unauthorized(conn) do 
    conn 
    |> put_status(401) 
    |> put_view(MyApp.ErrorView) 
    |> render("401.json") 
    |> halt 
    end 

    def handle_not_found(conn) do 
    conn 
    |> put_status(404) 
    |> put_view(MyApp.ErrorView) 
    |> render("404.json") 
    |> halt 
    end 
end 

我abilities.ex:

defimpl Canada.Can, for: MyApp.User do 
    alias MyApp.Operation 
    alias MyApp.User 

    def can?(user, action, operation = %Operation{}) when action in [:show, :update, :delete] do 
    IO.puts "check ability for operation" 
    if operation.user_id == user.id do 
     IO.puts "success" 
     true 
    else 
     false 
    end 
    end 

    def can?(subject, action, resource) do 
    raise """ 
    Unimplemented authorization check for User! To fix see below... 

    Please implement `can?` for User in #{__ENV__.file}. 

    The function should match: 

    subject: #{inspect subject} 

    action: #{action} 

    resource: #{inspect resource} 
    """ 
    end 
end 

而且unauthorized_handler工作正常。但是not_found_handler不起作用。

[error] #PID<0.709.0> running MyApp.Endpoint terminated 
Server: localhost:4000 (http) 
Request: GET /api/v1/operations/11 
** (exit) an exception was raised: 
    ** (RuntimeError) Unimplemented authorization check for User! To fix see below... 

Please implement `can?` for User in /home/mars/phoenix_projects/my_app/lib/abilities.ex. 

如果我添加到我的abilities.ex此功能:

def can?(user, action, nil) do 
    IO.puts "check ability for nil" 
    false 
    end 

如果未找到資源,我會叫handle_unauthorized

如果我離開只是

def can?(user, action, operation = %Operation{}) when action in [:show, :update, :delete] do 

然後我會有一個錯誤

(FunctionClauseError) no function clause matching in Canada.Can.MyApp.User.can?/3 

我不明白,我怎麼需要編寫一個函數,這種情況下

UPD:完整的錯誤信息:

[error] #PID<0.427.0> running MyApp.Endpoint terminated 
Server: localhost:4000 (http) 
Request: GET /api/v1/operations/11 
** (exit) an exception was raised: 
    ** (RuntimeError) Unimplemented authorization check for User! To fix see below... 

Please implement `can?` for User in /home/mars/phoenix_projects/my_app/lib/abilities.ex. 

The function should match: 

subject: %MyApp.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, operations: [%MyApp.Operation{__meta__: #Ecto.Schema.Metadata<:loaded, "operations">, balance: 1.3e3, categories: #Ecto.Association.NotLoaded<association :categories is not loaded>, id: 1, inserted_at: ~N[2017-04-15 15:00:38.727984], name: "new name", updated_at: ~N[2017-04-15 15:45:08.860944], users: #Ecto.Association.NotLoaded<association :users is not loaded>}, %MyApp.Operation{__meta__: #Ecto.Schema.Metadata<:loaded, "operations">, balance: 0.0, categories: #Ecto.Association.NotLoaded<association :categories is not loaded>, id: 2, inserted_at: ~N[2017-04-15 15:00:59.396742], name: "test1", updated_at: ~N[2017-04-15 15:00:59.396747], users: #Ecto.Association.NotLoaded<association :users is not loaded>}, %MyApp.Operation{__meta__: #Ecto.Schema.Metadata<:loaded, "operations">, balance: 0.0, categories: #Ecto.Association.NotLoaded<association :categories is not loaded>, id: 3, inserted_at: ~N[2017-04-15 15:01:56.845078], name: "test0", updated_at: ~N[2017-04-15 15:01:56.845085], users: #Ecto.Association.NotLoaded<association :users is not loaded>}, %MyApp.Operation{__meta__: #Ecto.Schema.Metadata<:loaded, "operations">, balance: 0.0, categories: #Ecto.Association.NotLoaded<association :categories is not loaded>, id: 4, inserted_at: ~N[2017-04-15 15:04:25.647952], name: "testtt", updated_at: ~N[2017-04-15 15:04:25.647958], users: #Ecto.Association.NotLoaded<association :users is not loaded>}], confirmation_token: nil, confirmed: false, id: 1, inserted_at: ~N[2017-04-15 14:58:48.263515], login: "test user0", password: nil, password_confirmation: nil, password_hash: "$2b$12$8yt6WNBt5hyxZE1MqiZtX.YRuReOuy4zom1imQvK2Q.Dw6pc8iNSG", reset_password_token: nil, sessions: #Ecto.Association.NotLoaded<association :sessions is not loaded>, updated_at: ~N[2017-04-15 14:58:48.268564]} 

action: show 

resource: nil 

     (my_app) lib/abilities.ex:43: Canada.Can.MyApp.User.can?/3 
     (canary) lib/canary/plugs.ex:214: Canary.Plugs.do_authorize_resource/2 
     (canary) lib/canary/plugs.ex:187: Canary.Plugs.authorize_resource/2 
     (canary) lib/canary/plugs.ex:274: Canary.Plugs.do_load_and_authorize_resource/2 
     (my_app) web/controllers/v1/operation_controller.ex:1: MyApp.V1.OperationController.phoenix_controller_pipeline/2 
     (my_app) lib/my_app/endpoint.ex:1: MyApp.Endpoint.instrument/4 
     (my_app) lib/phoenix/router.ex:261: MyApp.Router.dispatch/2 
     (my_app) web/router.ex:1: MyApp.Router.do_call/2 
     (my_app) lib/my_app/endpoint.ex:1: MyApp.Endpoint.phoenix_pipeline/1 
     (my_app) lib/plug/debugger.ex:123: MyApp.Endpoint."call (overridable 3)"/2 
     (my_app) lib/my_app/endpoint.ex:1: MyApp.Endpoint.call/2 
     (plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4 
     (cowboy) /home/mars/phoenix_projects/my_app/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4 
+0

你能發佈完整的錯誤信息嗎?它還應該印出主題,行動和資源的實際價值,這將有助於使問題更清楚。 – Dogbert

+0

@Dogbert,加了 –

+1

自從我使用加那利以來,它已經有一段時間了。我建議你嘗試返回一個無資源的'true'。我相信這會允許找不到的代碼運行。查看[Canary Plugs]的實現(https://github.com/cpjk/canary/blob/master/lib/canary/plugs.ex)獲取更多信息。 –

回答

1

如果爲can?(_, _, nil)功能的語句返回true,這將允許授權傳遞和handle_not_found插件正確設置conn