Closed devekko closed 7 years ago
@devekko it looks like canary is looking for the current user to authorize under conn.assigns[:guardian_default_resource]
, but you have loaded the current user under conn.assigns[:current_user]
. Check out the line in question in canary (from your stack trace).
IIRC, by default Guardian loads the current user under conn.assigns[:guardian_default_user]
, so you just need to configure canary to look there. The canary README explains how to do this, and you can also check out this line in this small project that does the same thing.
Also, I remember seeing this blog post about using canary with guardian and phoenix, but it's been a while since I read it, and I can't remember whether or not his approach was ideal :smile_cat:.
hmm, actually its
[info] GET /spaces
[debug] QUERY OK source="guardian_tokens" db=3.3ms
SELECT g0."jti", g0."typ", g0."aud", g0."iss", g0."sub", g0."exp", g0."jwt", g0."claims", g0."inserted_at", g0."updated_at" FROM "guardian_tokens" AS g0 WHERE ((g0."jti" = $1) AND (g0."aud" = $2)) ["bbe8075b-b204-4cd3-bb04-8871dc18e7d8", "User:1"]
[debug] QUERY OK source="users" db=1.3ms queue=0.2ms
SELECT u0."id", u0."name", u0."email", u0."bio", u0."zipcode", u0."address", u0."phone", u0."inserted_at", u0."updated_at" FROM "users" AS u0 WHERE (u0."id" = $1) [1]
[debug] Processing by SavesonomacountyOrg.SpaceController.index/2
Parameters: %{}
Pipelines: [:browser, :browser_auth, :require_login]
[debug] QUERY OK source="spaces" db=0.8ms queue=0.2ms
SELECT s0."id", s0."name", s0."user_id", s0."inserted_at", s0."updated_at" FROM "spaces" AS s0 []
[info] Sent 500 in 24ms
[error] #PID<0.471.0> running SavesonomacountyOrg.Endpoint terminated
Server: website.io:4000 (http)
Request: GET /spaces
** (exit) an exception was raised:
** (KeyError) key :guardian_default_resource not found in: %{current_user: %SavesonomacountyOrg.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, address: nil, authorizations: #Ecto.Association.NotLoaded<association :authorizations is not loaded>, bio: nil, email: "niccolo.roberts@gmail.com", id: 1, inserted_at: #Ecto.DateTime<2016-11-06 21:46:22>, name: "Nicholas Roberts", phone: nil, spaces: #Ecto.Association.NotLoaded<association :spaces is not loaded>, updated_at: #Ecto.DateTime<2016-11-06 21:46:22>, zipcode: nil}, spaces: [%SavesonomacountyOrg.Space{__meta__: #Ecto.Schema.Metadata<:loaded, "spaces">, id: 2, inserted_at: #Ecto.DateTime<2016-11-06 21:58:34>, name: "rr2", updated_at: #Ecto.DateTime<2016-11-06 21:58:44>, user: #Ecto.Association.NotLoaded<association :user is not loaded>, user_id: 1}]}
(elixir) lib/map.ex:164: Map.fetch!/2
lib/canary/plugs.ex:193: Canary.Plugs._authorize_resource/2
lib/canary/plugs.ex:186: Canary.Plugs.authorize_resource/2
lib/canary/plugs.ex:267: Canary.Plugs._load_and_authorize_resource/2
(savesonomacounty_org) web/controllers/space_controller.ex:3: SavesonomacountyOrg.SpaceController.phoenix_controller_pipeline/2
(savesonomacounty_org) lib/savesonomacounty_org/endpoint.ex:1: SavesonomacountyOrg.Endpoint.instrument/4
(savesonomacounty_org) lib/phoenix/router.ex:261: SavesonomacountyOrg.Router.dispatch/2
(savesonomacounty_org) web/router.ex:1: SavesonomacountyOrg.Router.do_call/2
(savesonomacounty_org) lib/savesonomacounty_org/endpoint.ex:1: SavesonomacountyOrg.Endpoint.phoenix_pipeline/1
(savesonomacounty_org) lib/plug/debugger.ex:123: SavesonomacountyOrg.Endpoint."call (overridable 3)"/2
(savesonomacounty_org) lib/savesonomacounty_org/endpoint.ex:1: SavesonomacountyOrg.Endpoint.call/2
(plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
(cowboy) src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4
that blog http://learningelixir.joekain.com/using-guardian-and-canary-with-phoenix/ directed me to use Canary in the first place
as far as I can tell I have assembled a relatively undocumented mix.exs
defp deps do
[{:phoenix, "~> 1.2.1"},
{:phoenix_pubsub, "~> 1.0"},
{:phoenix_ecto, "~> 3.0"},
{:postgrex, ">= 0.0.0"},
{:phoenix_html, "~> 2.6"},
{:phoenix_live_reload, "~> 1.0", only: :dev},
{:gettext, "~> 0.11"},
{:cowboy, "~> 1.0"},
{:canary, github: "cpjk/canary"},
{:guardian, "~> 0.13.0"},
{:guardian_db, "~> 0.7"},
{:ueberauth, github: "ueberauth/ueberauth", override: true},
{:ueberauth_github, "~>0.4.0"},
{:ueberauth_identity, "~>0.2.3"},
{:ueberauth_slack, "~>0.4.0"},
{:ueberauth_google, "~> 0.4.0"},
{:ueberauth_facebook, "~> 0.5.0"},
{:comeonin, "~> 2.6"}]
end
I have all the config as documented, I think its guardian db
it might also be abilities.ex
lib/abilities.ex
defmodule SavesonomacountyOrg.Abilities do
alias SavesonomacountyOrg.User
defimpl Canada.Can, for: User do
def can?(%User{}, :index, Space), do: true
def can?(%User{}, action, Space)
when action in [:new, :create], do: true
def can?(%User{}, _, _), do: false
end
end
config/config.exs
config :guardian, Guardian,
issuer: "SavesonomacountyOrg.#{Mix.env}",
ttl: {30, :days},
verify_issuer: true,
serializer: SavesonomacountyOrg.GuardianSerializer,
secret_key: to_string(Mix.env),
hooks: GuardianDb,
permissions: %{
default: [
:read_profile,
:write_profile,
:read_token,
:revoke_token,
],
}
config :guardian_db, GuardianDb,
repo: SavesonomacountyOrg.Repo,
sweep_interval: 60 # 60 minutes
config :canary,
repo: SavesonomacountyOrg.Repo,
current_user: :guardian_default_resource
will open source the site during week, I was going to back out and go with Coherence and Ex Admin but I am too stubborn
@devekko I would stick an IEx.pry binding before the canary plug in your controller, and check the contents of conn.assigns
. From your stack trace, it looks like you are storing the user under conn.assigns[:current_user]
instead of conn.assigns[:guardian_default_resource]
pry(7)> conn.assigns
%{current_user: %SavesonomacountyOrg.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
address: nil,
authorizations: #Ecto.Association.NotLoaded<association :authorizations is not loaded>,
bio: nil, email: "niccolo.roberts+admin@gmail.com", id: 2,
inserted_at: #Ecto.DateTime<2016-11-06 22:10:17>, name: "n", phone: nil,
spaces: #Ecto.Association.NotLoaded<association :spaces is not loaded>,
updated_at: #Ecto.DateTime<2016-11-06 22:10:17>, zipcode: nil},
spaces: [%SavesonomacountyOrg.Space{__meta__: #Ecto.Schema.Metadata<:loaded, "spaces">,
id: 2, inserted_at: #Ecto.DateTime<2016-11-06 21:58:34>, name: "rr2",
updated_at: #Ecto.DateTime<2016-11-06 21:58:44>,
user: #Ecto.Association.NotLoaded<association :user is not loaded>,
user_id: 1}]}
If you look at the output of the first command, you'll see current_user
. In the second and third you are passing a variable to the []
operator instead of a symbol. Use :current_user
instead of current_user
thanks, like this?
pry(6)> conn.assigns[:current_user]
%SavesonomacountyOrg.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">,
address: nil,
authorizations: #Ecto.Association.NotLoaded<association :authorizations is not loaded>,
bio: nil, email: "niccolo.roberts@gmail.com", id: 1,
inserted_at: #Ecto.DateTime<2016-11-06 21:46:22>, name: "Nicholas Roberts",
phone: nil,
spaces: #Ecto.Association.NotLoaded<association :spaces is not loaded>,
updated_at: #Ecto.DateTime<2016-11-06 21:46:22>, zipcode: nil}
pry(7)> conn.assigns[:guardian_default_resource]
nil
Yes.
pry(8)> conn
%Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...},
assigns: %{current_user: %SavesonomacountyOrg.User{__meta__: #Ecto.Schema.Metadata<:loaded,
If you read your comment here https://github.com/cpjk/canary/issues/51#issuecomment-258736323 you can see that there is no user where you told canary to look for it. You should configure canary to look for the current user under conn.assigns[:current_user]
, since that is where you are putting it.
thanks, I think that fixed it !
I think my error was to have changed default canary config to guardian_default_resource AND have a Guardian helper module as in the blog posts
defmodule MyApp.Plug.CurrentUser do
def init(opts), do: opts
def call(conn, _opts) do
current_user = Guardian.Plug.current_resource(conn)
Plug.Conn.assign(conn, :current_user, current_user)
end
end
I think I kind of cancelled myself out
now, its working (I think)
great, closing
hey there
am wondering if Canary works ok with Guardian DB?
this is my first Phoenix app and so am unsure exactly if this is a Canary issue BUT
when my controller is only loading resources via Canary I am ok
will follow-up with file info
been going round in circles on this for a few days now
when my controller is trying to authorize I get Guardian DB errors