Exception in transformer AshAuthentication.Strategy.Custom.Transformer

Hi there. I got an exception in transformer AshAuthentication.Strategy.Custom.Transformer when following the Authentication guide . Instead of User I set the resource name to Usuario.
== Compilation error in file lib/garagem/seguranca/resources/usuario.ex ==
** (RuntimeError) Exception in transformer AshAuthentication.Strategy.Custom.Transformer on Garagem.Seguranca.Usuario:

expected a map, got: nil
(elixir 1.15.4) lib/map.ex:486: Map.take/2
(ash_authentication 3.11.14) lib/ash_authentication/strategies/password/transformer.ex:78: anonymous fn/2 in AshAuthentication.Strategy.Password.Transformer.transform/2
...
== Compilation error in file lib/garagem/seguranca/resources/usuario.ex ==
** (RuntimeError) Exception in transformer AshAuthentication.Strategy.Custom.Transformer on Garagem.Seguranca.Usuario:

expected a map, got: nil
(elixir 1.15.4) lib/map.ex:486: Map.take/2
(ash_authentication 3.11.14) lib/ash_authentication/strategies/password/transformer.ex:78: anonymous fn/2 in AshAuthentication.Strategy.Password.Transformer.transform/2
...
mix.exs
...
{:ash, "~> 2.14"},
{:ash_postgres, "~> 1.3"},
{:ash_phoenix, "~> 1.2"},
{:ash_authentication, "~> 3.11"},
{:ash_authentication_phoenix, "~> 1.8"}
...
...
{:ash, "~> 2.14"},
{:ash_postgres, "~> 1.3"},
{:ash_phoenix, "~> 1.2"},
{:ash_authentication, "~> 3.11"},
{:ash_authentication_phoenix, "~> 1.8"}
...
Resource file
defmodule Garagem.Seguranca.Usuario do
use Ash.Resource,
data_layer: AshPostgres.DataLayer,
extensions: [AshAuthentication]

attributes do
uuid_primary_key :id
attribute :email, :ci_string, allow_nil?: false
attribute :hashed_password, :string, allow_nil?: false, sensitive?: true
end

authentication do
api Garagem.Seguranca

strategies do
password :password do
identity_field :email
sign_in_tokens_enabled? true
end
end

tokens do
enabled? true
token_resource Garagem.Seguranca.Token

signing_secret Garagem.Seguranca.Secrets
end
end

postgres do
table "usuarios"
repo Garagem.Repo
end

identities do
identity :unique_email, [:email]
end
end
defmodule Garagem.Seguranca.Usuario do
use Ash.Resource,
data_layer: AshPostgres.DataLayer,
extensions: [AshAuthentication]

attributes do
uuid_primary_key :id
attribute :email, :ci_string, allow_nil?: false
attribute :hashed_password, :string, allow_nil?: false, sensitive?: true
end

authentication do
api Garagem.Seguranca

strategies do
password :password do
identity_field :email
sign_in_tokens_enabled? true
end
end

tokens do
enabled? true
token_resource Garagem.Seguranca.Token

signing_secret Garagem.Seguranca.Secrets
end
end

postgres do
table "usuarios"
repo Garagem.Repo
end

identities do
identity :unique_email, [:email]
end
end
The resettable property of the struct strategy is nil at ash_authentication/strategies/password/transformer.ex:77. I tried to set the property to a function, as shown in the docs (https://hexdocs.pm/ash_authentication/AshAuthentication.Sender.html), but I still get the error. I hope someone can help me. Thanks
23 Replies
barnabasj
barnabasj2y ago
Are you sure you are getting the same error when adding the sender function like this?
strategies do
password :password do
identity_field :email
sign_in_tokens_enabled? true
resettable do
sender fn user, token ->
MyApp.Mailer.send_password_reset_email(user, token)
end
end
end
strategies do
password :password do
identity_field :email
sign_in_tokens_enabled? true
resettable do
sender fn user, token ->
MyApp.Mailer.send_password_reset_email(user, token)
end
end
end
I think I can see why it didn't work without it, but that should change with the resettable section being there
tellesleandro
tellesleandroOP2y ago
When I add as suggested, I get the following:
== Compilation error in file lib/garagem/seguranca/resources/usuario.ex ==
** (Spark.Error.DslError) [Garagem.Seguranca.Usuario]
authentication -> strategies -> resettable:
invalid value for :sender option: Expected a module and opts, or a 3 argument function. Got a 2 argument function.
lib/garagem/seguranca/resources/usuario.ex:27: (module)
== Compilation error in file lib/garagem/seguranca/resources/usuario.ex ==
** (Spark.Error.DslError) [Garagem.Seguranca.Usuario]
authentication -> strategies -> resettable:
invalid value for :sender option: Expected a module and opts, or a 3 argument function. Got a 2 argument function.
lib/garagem/seguranca/resources/usuario.ex:27: (module)
If I add the third argument, the program runs, but when I GET /sign-in, I get the following:
Server: localhost:4000 (http)
Request: GET /sign-in
** (exit) an exception was raised:
** (Protocol.UndefinedError) protocol Enumerable not implemented for %AshAuthentication.Strategy.Password.Resettable{token_lifetime: {3, :days}, request_password_reset_action_name: :request_password_reset_with_password, password_reset_action_name: :password_reset_with_password, sender: {AshAuthentication.SenderFunction, [fun: &Garagem.Seguranca.Usuario.sender_0_generated_D339B84297F4DD50933ACB55CC5208FD/3]}} of type AshAuthentication.Strategy.Password.Resettable (a struct). This protocol is implemented for the following type(s): DBConnection.PrepareStream, DBConnection.Stream, Date.Range, Ecto.Adapters.SQL.Stream, File.Stream, Function, GenEvent.Stream, HashDict, HashSet, IO.Stream, Jason.OrderedObject, List, Map, MapSet, Phoenix.LiveView.LiveStream, Postgrex.Stream, Range, Stream, StreamData
(elixir 1.15.4) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir 1.15.4) lib/enum.ex:166: Enumerable.reduce/3
(elixir 1.15.4) lib/enum.ex:409: Enum.any?/1
(ash_authentication_phoenix 1.8.1) lib/ash_authentication_phoenix/components/password.ex:111: AshAuthentication.Phoenix.Components.Password."render (overridable 1)"/1
Server: localhost:4000 (http)
Request: GET /sign-in
** (exit) an exception was raised:
** (Protocol.UndefinedError) protocol Enumerable not implemented for %AshAuthentication.Strategy.Password.Resettable{token_lifetime: {3, :days}, request_password_reset_action_name: :request_password_reset_with_password, password_reset_action_name: :password_reset_with_password, sender: {AshAuthentication.SenderFunction, [fun: &Garagem.Seguranca.Usuario.sender_0_generated_D339B84297F4DD50933ACB55CC5208FD/3]}} of type AshAuthentication.Strategy.Password.Resettable (a struct). This protocol is implemented for the following type(s): DBConnection.PrepareStream, DBConnection.Stream, Date.Range, Ecto.Adapters.SQL.Stream, File.Stream, Function, GenEvent.Stream, HashDict, HashSet, IO.Stream, Jason.OrderedObject, List, Map, MapSet, Phoenix.LiveView.LiveStream, Postgrex.Stream, Range, Stream, StreamData
(elixir 1.15.4) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir 1.15.4) lib/enum.ex:166: Enumerable.reduce/3
(elixir 1.15.4) lib/enum.ex:409: Enum.any?/1
(ash_authentication_phoenix 1.8.1) lib/ash_authentication_phoenix/components/password.ex:111: AshAuthentication.Phoenix.Components.Password."render (overridable 1)"/1
ZachDaniel
ZachDaniel2y ago
I've just pushed something up can you try main of ash_authentication?
tellesleandro
tellesleandroOP2y ago
Sure. Thanks. I let you know if it works.
ZachDaniel
ZachDaniel2y ago
🙇‍♂️
tellesleandro
tellesleandroOP2y ago
Zach, the patch solves the original problem related to the resettable property, but the one that pops when I request /sign-in still remains.
ZachDaniel
ZachDaniel2y ago
👍 taking a look now
tellesleandro
tellesleandroOP2y ago
Great. Let me know if you need any additional info.
ZachDaniel
ZachDaniel2y ago
I think I need to talk to @jart, as I think this was a very recent commit that caused the issue and while I can see how to fix it, I think there is some small but deeper cause are you on the latest version of both ash_authentication and ash_authentication_phoenix, just to check our bases?
tellesleandro
tellesleandroOP2y ago
Ok. I'm starting my journey with Ash (because of ElixirConf), that's why I'm following the guides. Take your time and I'm ok with that. These are the versions I'm running on: "ash": {:hex, :ash, "2.14.20" "ash_authentication": {:hex, :ash_authentication, "3.11.15" "ash_authentication_phoenix": {:hex, :ash_authentication_phoenix, "1.8.1" "ash_phoenix": {:hex, :ash_phoenix, "1.2.17" "ash_postgres": {:hex, :ash_postgres, "1.3.51"
ZachDaniel
ZachDaniel2y ago
I've got a similar set up to you on ash_hq so I'll see if I can get it reproduced 🙂
tellesleandro
tellesleandroOP2y ago
Allright. I'm here if you need some help with the setup.
ZachDaniel
ZachDaniel2y ago
yep! Going to latest versions gets me the same error once I have a reproduction, fixing is usually very easy 😄
tellesleandro
tellesleandroOP2y ago
I do believe. By the way, what a wonderful piece of technology you guys are doing. Congrats.
ZachDaniel
ZachDaniel2y ago
found the breaking commit, now to dissect 😄 Okay, so I see what the issue is, but the question is if I should roll forward by fixing ash_authentication_phoenix or undo the changes to ash_authentication... Probably the former
ZachDaniel
ZachDaniel2y ago
Alright, PR merged. It will auto release a new version. but you can also point at main if you'd like to try it in the next 10-15 minutes
tellesleandro
tellesleandroOP2y ago
Thanks a lot, Zach. I'll stop now for lunch. I'll be right back in 30 minutes. Talk to you after that. Zach, with the #279, I get the following error:
Server: localhost:4000 (http)
Request: GET /sign-in
** (exit) an exception was raised:
** (Protocol.UndefinedError) protocol Enumerable not implemented for nil of type Atom. This protocol is implemented for the following type(s): DBConnection.PrepareStream, DBConnection.Stream, Date.Range, Ecto.Adapters.SQL.Stream, File.Stream, Function, GenEvent.Stream, HashDict, HashSet, IO.Stream, Jason.OrderedObject, List, Map, MapSet, Phoenix.LiveView.LiveStream, Postgrex.Stream, Range, Stream, StreamData
(elixir 1.15.4) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir 1.15.4) lib/enum.ex:166: Enumerable.reduce/3
(elixir 1.15.4) lib/enum.ex:409: Enum.any?/1
(ash_authentication_phoenix 1.8.1) lib/ash_authentication_phoenix/components/password.ex:111: AshAuthentication.Phoenix.Components.Password."render (overridable 1)"/1
Server: localhost:4000 (http)
Request: GET /sign-in
** (exit) an exception was raised:
** (Protocol.UndefinedError) protocol Enumerable not implemented for nil of type Atom. This protocol is implemented for the following type(s): DBConnection.PrepareStream, DBConnection.Stream, Date.Range, Ecto.Adapters.SQL.Stream, File.Stream, Function, GenEvent.Stream, HashDict, HashSet, IO.Stream, Jason.OrderedObject, List, Map, MapSet, Phoenix.LiveView.LiveStream, Postgrex.Stream, Range, Stream, StreamData
(elixir 1.15.4) lib/enum.ex:1: Enumerable.impl_for!/1
(elixir 1.15.4) lib/enum.ex:166: Enumerable.reduce/3
(elixir 1.15.4) lib/enum.ex:409: Enum.any?/1
(ash_authentication_phoenix 1.8.1) lib/ash_authentication_phoenix/components/password.ex:111: AshAuthentication.Phoenix.Components.Password."render (overridable 1)"/1
I inspected the strategy struct right before password.ex:111 and got the following:
%AshAuthentication.Strategy.Password{
confirmation_required?: true,
hash_provider: AshAuthentication.BcryptProvider,
hashed_password_field: :hashed_password,
identity_field: :email,
name: :password,
password_confirmation_field: :password_confirmation,
password_field: :password,
provider: :password,
register_action_accept: [],
register_action_name: :register_with_password,
registration_enabled?: true,
resettable: nil,
resource: Garagem.Seguranca.Usuario,
sign_in_action_name: :sign_in_with_password,
sign_in_enabled?: true,
sign_in_token_lifetime: {60, :seconds},
sign_in_tokens_enabled?: true,
sign_in_with_token_action_name: :sign_in_with_token_for_password,
strategy_module: AshAuthentication.Strategy.Password
}
%AshAuthentication.Strategy.Password{
confirmation_required?: true,
hash_provider: AshAuthentication.BcryptProvider,
hashed_password_field: :hashed_password,
identity_field: :email,
name: :password,
password_confirmation_field: :password_confirmation,
password_field: :password,
provider: :password,
register_action_accept: [],
register_action_name: :register_with_password,
registration_enabled?: true,
resettable: nil,
resource: Garagem.Seguranca.Usuario,
sign_in_action_name: :sign_in_with_password,
sign_in_enabled?: true,
sign_in_token_lifetime: {60, :seconds},
sign_in_tokens_enabled?: true,
sign_in_with_token_action_name: :sign_in_with_token_for_password,
strategy_module: AshAuthentication.Strategy.Password
}
resettable is nil.
ZachDaniel
ZachDaniel2y ago
🤔 that line of code isn't right based on what I'm looking at ash_authentication_phoenix 1.8.1, 1.8.2 should be out w/ the fix now can you try that published version?
tellesleandro
tellesleandroOP2y ago
I'll do it now. Bingo. That worked. I'll keep moving forward and let you know if something brakes. Thanks a lot, Zach. I hope someday I can contribute to this project.
ZachDaniel
ZachDaniel2y ago
🥳 we'd welcome any contribution you'd like to make, but you've also already contributed 😄 You found and reported a bug, and helped us ensure it was fixed!
tellesleandro
tellesleandroOP2y ago
I'm getting used to the Ash's code. As soon as I feel that I understand that, I think I can help more. I'll be glad to be part of it. Thanks a lot, Zach.
jart
jart2y ago
This is my fault and I am a bad bad person. Thanks @Zach Daniel for cleaning up my mess.

Did you find this page helpful?