How to use generated phoenix auth user as a resource within an ash relationship?

Hey guys :slight_smile:
I am quite new to elixir and super fresh in ash.

I already have an app built with phoenix and wanted to use ash with it now. I already have all the auth i need thanks to the gen.auth command. Everything works great and i got a poc working without ash.

Now i want to model my domains with ash and use the benefits it brings to the table.

I have a tenant resource that belongs to a user and this user is the owner. So i tried to model it according to the docs:

defmodule App.Tenant do
  use Ash.Resource,
    data_layer: AshPostgres.DataLayer

  postgres do
    table "tenants"
    repo App.Repo

  attributes do
    uuid_primary_key :id
    attribute :name, :string

  relationships do
    belongs_to :owner, App.Users.User

  actions do
    defaults [:read, :destroy, create: :*, update: :*]

But this of course does not work as the User is not a Spark DSL Entity/Resource…

Maybe a noob question and possibly i misread something in the docs, but i thought i do not have to use ash_auth and can still use the phoenix generated auth solution.

So how do i work with this?

  • do i have to implement ash auth to make it work?
  • do i have to extend the user module with some spark dsl sprinkle magic to make it work?
  • can i define the relationship in another way? i mean it is basically a helper for creating a cross table, right?

Thanks in advance for any help :slight_smile:

I am afraid you may have two options:

  1. Use Ash authentication (I recommend this).
  2. Create two different Repos. One for Ash another for the traditional Ecto.

If you go with the first option and your app has unit tests for protected route, you will have to also change the way you authenticate the user to the following

      def login(conn, username \\ "") do
        {:ok, user} = create_user(username)
        |> Phoenix.ConnTest.init_test_session(%{})
        |> put_session(:user, "user?id=#{}")
1 Like

You can use the generated Phoenix auth in at least two ways:

  1. Refactor the Ecto schemas into Ash resources and the auth contexts to Ash actions.
  2. Duplicate the user Ecto schema as an Ash resource, and use that as the actor.

The actor in Ash is just a map, so you could just pass it the Ecto version of the user, but (I think) it will have a lot of limitations. For example, policies that leverage things like relates_to_actor_via etc and other relationship-related things won’t work.

There is a not currently a way to sprinkle some magic onto an Ecto schema to turn it into an Ash resource, but it has been discussed in the past (actually, moreso the other way around, Ash → Ecto). But there are some tricky problems regarding doing that, so I think it’s not really planned at the moment.

1 Like

The relates_to_actor_via should actually continue to work, because we just grab the appropriate destination attributes from the user. If you want to relate a resource to your “user”, it will have to be a User. With that said, you can have an ecto schema for User and an Ash.Resource for User just fine :slight_smile:

1 Like

This sounds very promising. I will try that and will come back when i got it working. Thanks a lot!

1 Like

So far that seems to work! Now my app compiles and when registering users everything works fine :slight_smile: