How does AshAuthentication monitor_fields work?

I was looking into the confirmation addon for AshAuthentication and started wondering what is needed to make monitor_fields work. For example, I have that field set as monitor_fields: [:email] What exactly does that do? Does it "automagically" inserts a change on each action that can change the email field? From my tests, that's not the case, I have an action like this:
update :change_email do
alias Actions.ChangeEmail.Changes

accept [:email]
end
update :change_email do
alias Actions.ChangeEmail.Changes

accept [:email]
end
And nothing happens, an I missing something? Should I add some specific change to that action so these fields start to work?
12 Replies
ZachDaniel
ZachDaniel2y ago
The purpose of monitoring the fields is to inhibit changes of those fields pending confirmation Not to allow them to be changed
Blibs
BlibsOP2y ago
Hmm, but that's not my question actualy, in the documentation it says: The confirmation will only be sent when one of these fields are changed. What I understand from this is that it will only trigger the sender function if that field changes. But on which action? I mean, that action that I showed before changes the e-mail, but it doesn't trigger the email sender at all. Same thing as the confirm_on_create? which is true by default. From its description, it says that it will generate and send a token when a new resource is created, but when I create one it doesn't trigger the sender at all
ZachDaniel
ZachDaniel2y ago
Oh, interesting. Yeah you’re right, by default it doesn’t actually inhibit the changes
Blibs
BlibsOP2y ago
I think I found the issue (need to test more to confirm it solves all of them), when you create the add on, you can change its name, in my case, mine is like this:
confirmation :email_confirmation do
monitor_fields [:email]

confirm_action_name :verify_email

sender Senders.SendConfirmationEmail
end
confirmation :email_confirmation do
monitor_fields [:email]

confirm_action_name :verify_email

sender Senders.SendConfirmationEmail
end
And looking into the file AshAuthentication.AddOn.Confirmation.ConfirmationHookChange it checks for a stratagy called :confirm, meaning that, if I don't use the name as the documentation example shows, it breaks that change
ZachDaniel
ZachDaniel2y ago
Oh, really?
Blibs
BlibsOP2y ago
Changing its name to :confirm made my change_email action send the email at least
ZachDaniel
ZachDaniel2y ago
That sounds like a bug Yep, that’s a bug. Can you open an issue on ash_authentication please? @jart FYI ^ Thanks for finding the issue.
Blibs
BlibsOP2y ago
Of course 🙂 , I need to leave the computer right now, but I will create it ASAP when I'm back
ZachDaniel
ZachDaniel2y ago
Thanks 🙂
Blibs
BlibsOP2y ago
GitHub
bug: ConfirmationHookChange only work if strategy name is :confirm ...
This can be seen in this line of the file: ash_authentication/lib/ash_authentication/add_ons/confirmation/confirmation_hook_change.ex Line 16 in cc3aa41 case Info.strategy(changeset.resource, :conf...
Blibs
BlibsOP2y ago
done So, this also made me wonder, is there any easy way to create a "resend token e-mail" action for cases where the user, for whatever reason didn't received the token yet? My current solution is create a action with a change like this:
update :send_confirmation_email do
alias Actions.SendConfirmationEmail.Changes

accept []

change Changes.SendConfirmationEmail
end
update :send_confirmation_email do
alias Actions.SendConfirmationEmail.Changes

accept []

change Changes.SendConfirmationEmail
end
defmodule FeedbackCupcake.Accounts.User.Actions.SendConfirmationEmail.Changes.SendConfirmationEmail do
@moduledoc """
Sends a email with the confirmation token
"""

alias FeedbackCupcake.Accounts.User.Senders

use Ash.Resource.Change

def change(changeset, _opts, _context), do: Ash.Changeset.after_action(changeset, &do_change/2)

defp do_change(changeset, user) do
strategy = AshAuthentication.Info.strategy!(changeset.resource, :confirm)

{:ok, token} =
AshAuthentication.AddOn.Confirmation.confirmation_token(strategy, changeset, changeset.data)

Senders.SendConfirmationEmail.send(changeset.data, token, [])

{:ok, user}
end
end
defmodule FeedbackCupcake.Accounts.User.Actions.SendConfirmationEmail.Changes.SendConfirmationEmail do
@moduledoc """
Sends a email with the confirmation token
"""

alias FeedbackCupcake.Accounts.User.Senders

use Ash.Resource.Change

def change(changeset, _opts, _context), do: Ash.Changeset.after_action(changeset, &do_change/2)

defp do_change(changeset, user) do
strategy = AshAuthentication.Info.strategy!(changeset.resource, :confirm)

{:ok, token} =
AshAuthentication.AddOn.Confirmation.confirmation_token(strategy, changeset, changeset.data)

Senders.SendConfirmationEmail.send(changeset.data, token, [])

{:ok, user}
end
end
This works, but I would prefer to not have to implement that change and use something directly from AshAuthentication if possible.
ZachDaniel
ZachDaniel2y ago
Hmm...its not implemented currently, but sounds like a good potential addition to ash_authentication or at least, I think its not implemented currently? worth making an issue and asking @jart about it 😄

Did you find this page helpful?