How to confirm users created in seeds with AshAuthentication?

I’m using AshAuthentication and have configured the :password strategy with require_confirmed_with :confirmed_at.
I want users created via register_with_password in my seeds to be automatically confirmed.

defmodule MyApp.Resources.Accounts.User do
  ...
 
  authentication do
    strategies do
      password :password do
        identity_field :email
        require_confirmed_with :confirmed_at
      end
    end
    
    add_ons do
      confirmation :confirm do
        monitor_fields [:email]
        confirmed_at_field :confirmed_at
      end
    end
  end
end

I’ve checked the documentation, particularly the example here, but I’m unsure how to get the confirmation token in this case.

# seeds

user = MyApp.Resources.Accounts.User.register_with_password!(%{
  email: "noname@devall.org",
  password: "password",
  password_confirmation: "password",
})

strategy = AshAuthentication.Info.strategy!(MyApp.Resources.Accounts.User, :confirm)

# how can I get confirmation token?
AshAuthentication.Strategy.action(strategy, :confirm, %{"confirm" => ?})

Thanks

If you have store_all_tokens? true in your token config then you could read the token from the database potentially.

Additionally, you could use Ash.Seed Ash.Seed.update! would do it.

1 Like

How can I generate a JWT after successfully retrieving a token as shown below?
I found the AshAuthentication.Jwt.token_for_user/2 function to generate a token from a user, but I don’t know how to generate a token from a token resource.

confirmation_token =
  MyApp.Resources.Accounts.Token
  |> Ash.Query.filter(purpose == "confirm" and subject == ^"user?id=#{user.id}")
  |> Ash.read_one!()

My current implementation looks like this:

#seeds.exs
strategy = AshAuthentication.Info.strategy!(MyApp.User, :password)

{:ok, user} = 
  AshAuthentication.Strategy.action(strategy, :register, %{
    email: System.fetch_env!("USER_EMAIL"),
    password: System.fetch_env!("USER_PASSWORD"),
    password_confirmation: System.fetch_env!("USER_PASSWORD")
    })

Ash.Seed.update!(user, %{confirmed_at: DateTime.utc_now()}) end

Because Ash.Seed.seed! bypasses action logic and just writes straight to the datalayer, you can just generate a user in the state you want:

Ash.Seed.seed!(%MyApp.User{
  email: Faker.Internet.email(),
  hashed_password: Bcrypt.hash_pwd_salt(Faker.UUID.v4()),
  confirmed_at: DateTime.utc_now(),
})
2 Likes

Thank you, this is a lot more straightforward!

The reason I want to call the confirm action is that I’m unsure if it only affects confirmed_at.
Can I be confident about this and use it as is?

I don’t believe that there is a way to get the specific confirmation jwt that was sent to the user. If you wanted to test the flow, you could instead try testing it out by doing one of two things:

  1. setting up your mailer to send to your test process. I imagine swoosh has some stuff like this for asserting that emails were sent.
  2. generate a confirmation token yourself using something like AshAuthentication.Jwt.token_for_user(user, %{"act" => "confirm"}, token_lifetime: 1), and then use that.
1 Like

@jimsynz please correct me if I’m wrong

not wrong.