ueberauth / guardian

Elixir Authentication
MIT License
3.43k stars 382 forks source link

Dialyzer throwing un necessary warnings #565

Closed shanmugharajk closed 5 years ago

shanmugharajk commented 5 years ago

I am using the vs-code extension https://marketplace.visualstudio.com/items?itemName=JakeBecker.elixir-ls

Environment details

Erlang/OTP 21 [erts-10.2.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe] [dtrace]

Elixir 1.7.4 (compiled with Erlang/OTP 21)

My Guardian module code is as

defmodule Epos.Guardian do
  use Guardian,
    otp_app: :epos

  use Guardian.Permissions.Bitwise

  def subject_for_token(%{} = user, _claims) do
    # You can use any value for the subject of your token but
    # it should be useful in retrieving the resource later, see
    # how it being used on `resource_from_claims/1` function.
    # A unique `id` is a good subject, a non-unique email address
    # is a poor subject.
    sub = to_string(user.users_id)
    {:ok, sub}
  end

  def subject_for_token(_, _) do
    {:error, :reason_for_error}
  end

  def resource_from_claims(%{} = claims) do
    # Here we'll look up our resource from the claims, the subject can be
    # found in the `"sub"` key. In `above subject_for_token/2` we returned
    # the resource id so here we'll rely on that to look it up.

    id = claims["sub"]
    resource = Epos.Accounts.get_user!(id)
    {:ok, resource}
  end

  def resource_from_claims(_claims) do
    {:error, :reason_for_error}
  end

  def build_claims(claims, _resource, opts) do
    claims =
      claims
      |> encode_permissions_into_claims!(Keyword.get(opts, :permissions))

    {:ok, claims}
  end
end

The moment I include this use Guardian.Permissions.Bitwise i get the following warnings in vscode

The attempt to match a term of type ‘Elixir.MapSet’:t(_) against the pattern #{‘struct’:=‘Elixir.MapSet’} breaks the opacity of the term

Function ‘do_any_permissions?’/2 has no local return

The created fun has no local return

Invalid type specification for function ‘Elixir.Epos.Guardian’:available_permissions/0. The success typing is () -> #{‘admin’:=[‘expense_write’ | ‘products’ | ‘receivings_write’ | ‘sales’ | ‘stock’,…], ‘basic_user’:=[‘sales’ | ‘stock’,…], ‘super_admin’:=[‘all_access’,…]}

I tried googling but I am failed to figure the reason for this. Could somebody please help me on this?

doomspork commented 5 years ago

@shanmugharajk what version of Guardian are you using?

shanmugharajk commented 5 years ago

Mix config info

{:guardian, "~> 1.0"}

asummers commented 5 years ago

I did some minor debugging into this. You can get it working if any of:

1) available_permissions type relaxed to map 2) available_permissions type inlined to %{optional(atom) => [atom]} 3) available_permissions spec removed 4) Call to Guardian.Permissions.Bitwise.available_from_normalized(@normalized_perms) inlined into available_permissions.

These all have pretty self evident flaws.

Adding | [atom] to the type of permission_set did not work as expected. I'm very confused why this is failing.

shanmugharajk commented 5 years ago

Is it possible to suppress these warnings in my code?

blisscs commented 5 years ago

Hi, I am also getting dailyzer issue when running mix dialyzer, I wonder is there any progress on this issue.

yordis commented 5 years ago

@blisscs I don't think so since I just knew about it.

PR welcome 💜

Hanspagh commented 5 years ago

Running mix dialyzer on current master branch results in no errors. @blisscs @shanmugharajk could you verify this?

yordis commented 5 years ago

Hey folks, feel free to reopen the issue, I believe that this should be fixed already. v2 release is coming.

blisscs commented 5 years ago

Thank you @yordis and @Hanspagh for the updates.

I am currently using "~> 1.0" now, I am seeing that I need to do some other changes to use current master version here.

Will keep my version as it is for now. Once I try it will update here one again.

Best

shanmugharajk commented 5 years ago

@Hanspagh Yes, verified and the warnings are gone! Its fine now.

shanmugharajk commented 5 years ago

Sorry again, I got another problem now this is my config

issuer: "epos",
secret_key: "+rENf7iolLX1ySSwS6smLJ+p/5ArJsI8DAgjhuCUMBFszV9aul8SO4jncpcfhS1x",
permissions: %{
basic_user: [
    :sales,
    :stock
],
super_admin: [
    :all_access
],
admin: [
    :sales,
    :stock,
    :products,
    :expense_write,
    :receivings_write
]
}

and when i call this use Guardian.Permissions.Bitwise like this

defmodule Epos.Guardian do
  use(Guardian,
    otp_app: :epos
  )

  use Guardian.Permissions.Bitwise

  def subject_for_token(%{} = user, _claims) do
    # You can use any value for the subject of your token but
    # it should be useful in retrieving the resource later, see
    # how it being used on `resource_from_claims/1` function.
    # A unique `id` is a good subject, a non-unique email address
    # is a poor subject.
    sub = to_string(user.users_id)
    {:ok, sub}
  end

  def subject_for_token(_, _) do
    {:error, :reason_for_error}
  end

  def resource_from_claims(%{} = claims) do
    # Here we'll look up our resource from the claims, the subject can be
    # found in the `"sub"` key. In `above subject_for_token/2` we returned
    # the resource id so here we'll rely on that to look it up.

    id = claims["sub"]
    resource = Epos.Accounts.get_user(id)
    {:ok, resource}
  end

  def resource_from_claims(_claims) do
    {:error, :reason_for_error}
  end

  def build_claims(claims, _resource, opts) do
    claims =
      claims
      |> encode_permissions_into_claims!(Keyword.get(opts, :permissions))

    {:ok, claims}
  end
end

I am getting error says

Invalid type specification for function 'Elixir.Epos.Guardian':available_permissions/0. The success typing is () -> #{'admin':=['expense_write' | 'products' | 'receivings_write' | 'sales' | 'stock',...], 'basic_user':=['sales' | 'stock',...], 'super_admin':=['all_access',...]}

I am not sure I can ask this here or stack overflow. If this is not right here please ignore this.

What I tried to get rid of the initial problem is updated from 1.0 to {:guardian, "~> 1.2"}

mix clean
mix deps.get
mix compile

Now the previous errors were gone and got the above said one 😢

yordis commented 5 years ago

Is that the whole message?

shanmugharajk commented 5 years ago

yes thats the whole message I am getting in the vscode console.

Screenshot 2019-05-24 at 11 38 14 AM
yordis commented 5 years ago

@shanmugharajk there is an incoming change that touches a lot in Permissions module so, I will wait until that is out and then figure out if this still an issue.

Please, give us some time to prepare v2 release and let's see if the issue persist.

wolfiton commented 5 years ago

if you still have some problems and warnings with dialyzer this is how I solved it. I changed the original code offered for "Create a module that uses Guardian"

original code:

defmodule MyApp.Guardian do
  use Guardian, otp_app: :my_app

  def subject_for_token(resource, _claims) do
    # You can use any value for the subject of your token but
    # it should be useful in retrieving the resource later, see
    # how it being used on `resource_from_claims/1` function.
    # A unique `id` is a good subject, a non-unique email address
    # is a poor subject.
    sub = to_string(resource.id)
    {:ok, sub}
  end
  def subject_for_token(_, _) do
    {:error, :reason_for_error}
  end

  def resource_from_claims(claims) do
    # Here we'll look up our resource from the claims, the subject can be
    # found in the `"sub"` key. In `above subject_for_token/2` we returned
    # the resource id so here we'll rely on that to look it up.
    id = claims["sub"]
    resource = MyApp.get_resource_by_id(id)
    {:ok,  resource}
  end
  def resource_from_claims(_claims) do
    {:error, :reason_for_error}
  end
end`

**Changed code:**

defmodule MyApp.Guardian do
  use Guardian, otp_app: :my_app

  def subject_for_token(resource, _claims) do
    # You can use any value for the subject of your token but
    # it should be useful in retrieving the resource later, see
    # how it being used on `resource_from_claims/1` function.
    # A unique `id` is a good subject, a non-unique email address
    # is a poor subject.
    sub = to_string(resource.id)
    if sub do
     {:ok, sub}
    else
     {:error, :reason_for_error}
    end
  end

  def resource_from_claims(claims) do
    # Here we'll look up our resource from the claims, the subject can be
    # found in the `"sub"` key. In `above subject_for_token/2` we returned
    # the resource id so here we'll rely on that to look it up.
    id = claims["sub"]
    resource = MyApp.get_resource_by_id(id)
    if resource do
     {:ok, resource}
    else
     {:error, :reason_for_error}
    end
  end
end

After you change your code, dialyzer should stop showing any errors or warnings.

Hope this helps