Guardian.Permissions.Plug Issue when using one_of option
zacksiri opened this issue · 19 comments
** (Protocol.UndefinedError) protocol Enumerable not implemented for 0.
I'm getting this error when using the Guardian.Permissions.Plug
inside my controller and using the one_of
option the error is pointing to line 61 of the code which is
https://github.com/ueberauth/guardian/blob/master/lib/guardian/permissions/plug.ex#L61
I downgraded to version 1.2 and everything is working normally.
Hi @zacksiri. Did you see that we had a breaking change when upgrading to version 2.0
https://github.com/ueberauth/guardian/blob/master/CHANGELOG.md#breaking-change
@Hanspagh Hey I tried implementing the changes, I'm getting the same error. Actually before I saw the breaking changes I already read through the code to figure out to come to the same conclusion the only thing I didn't do was set the encoding option which I read in the code will set it to the BitwiseEncoding module by default already.
@zacksiri would be possible to create a PR replicating the issue in the tests?
It will help us to debug based on your use case, and it will easier to do some testing around the issue as well.
Otherwise, post some code snippets that could help us to know how you are using the feature.
@Hanspagh Hey no unfortunately I haven't had the time to create a sample project yet. I have downgraded to 1.2 for now since there are some projects I need to ship. I will upgrade my project again later to see if it still persists and will note down some code snippets.
@zacksiri Sure, I would really like to fix this thought, can you by any chance post what you have as params to one_of
. Something like this asuming you use plug
plug Guardian.Permissions.BitwiseEncoding. one_of: [
%{default: [:public_profile], user_actions: [:books]},
%{default: [:public_profile], user_actions: [:music]},
]
@Hanspagh Why is there a period after BitwiseEncoding in your example? Also in the documentation: https://github.com/ueberauth/guardian/blob/master/lib/guardian/permissions.ex#L88
== Compilation error in file lib/engine_web/router.ex ==
** (SyntaxError) lib/engine_web/router.ex:17: syntax error before: ensure
Shouldn't it be a comma as it was in Guardian 1.x?
I'm having trouble upgrading from Guardian 1.2.1 to 2.0, despite reviewing the changelog (thanks for the tip)
In guardian.ex:
use Guardian.Permissions.Bitwise
became:
use Guardian.Permissions, encoding: Guardian.Permissions.BitwiseEncoding
In router.ex:
plug(Guardian.Permissions.Bitwise, ensure: %{role: [:admin]})
became
plug(Guardian.Permissions.BitwiseEncoding, ensure: %{role: [:admin]})
Compile error:
== Compilation error in file lib/engine_web/router.ex ==
** (UndefinedFunctionError) function Guardian.Permissions.BitwiseEncoding.init/1 is undefined or private
Guardian.Permissions.BitwiseEncoding.init([ensure: %{role: [:admin]}])
(plug) lib/plug/builder.ex:304: Plug.Builder.init_module_plug/4
(plug) lib/plug/builder.ex:288: anonymous fn/5 in Plug.Builder.compile/3
(elixir) lib/enum.ex:1948: Enum."-reduce/3-lists^foldl/2-0-"/3
(plug) lib/plug/builder.ex:286: Plug.Builder.compile/3
@nathany That is a good catch. It should ofcuase be a comma. I took the example strait from the documentation, so we need to fix that.
@zacksiri here is what I have in the one_of. This is from version 1.2
that doesn't work with 2.0
plug Guardian.Permissions.Bitwise,
one_of: [
%{customer: [:verify_own_token]},
%{app: [:verify_own_token]}
]
plug Guardian.Permissions.BitwiseEncoding,
one_of: [
%{customer: [:verify_own_token]},
%{app: [:verify_own_token]}
]
Thanks @Hanspagh. When using a comma, any idea why I'm getting this Guardian.Permissions.BitwiseEncoding.init/1 is undefined or private
error (see #607 (comment))?
Yes. It is because we need to use plug(Guardian.Permissions.Plug)
and not plug(Guardian.Permissions.BitwiseEncoding)
. I am sorry for the inconvenience. I will update the docs right a way
Is there a resolution to this? I'm seeing the same ** (Protocol.UndefinedError) protocol Enumerable not implemented for 0.
for a user that doesn't have permissions for the application. In this case, I have a single-sign on system that the user may or may not have access to an app through permissions. So they're authenticated, but not authorized. (Permission set is empty for this app).
(For a user who does have permissions, it's fine.)
In 1.2 it would handle that scenario and fall into my AuthErrorHandler, in 2.0 I get the above exception.
defmodule MyAppPerm.Guardian do
use Guardian, otp_app: :my_app,
permissions: %{
league: [:aaf, :cfl, :xfl],
feeds: [:general, :fantasy, :analytics, :stats, :premium, :quality_control, :video],
ngs: [:all],
feature: [:override_trn],
admin: [:notifications],
}
use Guardian.Permissions, encoding: Guardian.Permissions.BitwiseEncoding
def subject_for_token(%{"email" => _} = token, _claims) do
{:ok, Jason.encode!(token)}
end
def subject_for_token(_resource, _claims) do
{:error, "Unknown resource type"}
end
def resource_from_claims(claims) do
Jason.decode(claims["sub"])
end
def build_claims(claims, _resource, opts) do
# Ensure there's at least one claim
{_, pems} =
opts
|> Keyword.get(:permissions)
|> Map.get_and_update("league", fn(p) ->
case p do
nil -> {nil, []}
v -> {v, v}
end
end)
|> IO.inspect()
encoded_claims =
encode_permissions_into_claims!(claims, pems)
|> IO.inspect()
{:ok, encoded_claims}
end
def preferences(conn) do
case MyAppPerm.Guardian.Plug.current_claims(conn) |> resource_from_claims() do
{:ok, %{"preferences" => prefs}} -> prefs
_ -> []
end
end
end
defmodule MyAppPerm.Guardian.AuthPipeline do
@claims %{typ: "access"}
use Guardian.Plug.Pipeline, otp_app: :my_app,
module: MyAppPerm.Guardian,
error_handler: MyAppPerm.Guardian.AuthErrorHandler
plug Guardian.Plug.VerifySession, claims: @claims
plug Guardian.Plug.EnsureAuthenticated
plug Guardian.Plug.LoadResource, allow_blank: false
# Must have access to one or more leagues
plug Guardian.Permissions.Plug, one_of: [
%{league: [:aaf]},
%{league: [:cfl]},
%{league: [:xfl]},
]
end
If I merge in a default set of permissions so that all of the keys exist in pems, then it works. That seems like a workaround to a code problem though.
default = %{
league: [],
feeds: [],
ngs: [],
feature: [],
admin: [],
}
pems = Map.merge(default, Keyword.get(:permissions)
encoded_claims =
encode_permissions_into_claims!(claims, pems)
{:ok, encoded_claims}
Thank you soo much @geofflane for the detailed bug report and the fixing PR
I have already added it here https://github.com/ueberauth/guardian/blob/master/CHANGELOG.md#bug-fix