how to config user_id inside PaperTrail

Hi, sorry. based on this doc https://hexdocs.pm/ash_paper_trail/getting-started-with-ash-paper-trail.html#associating-versions-with-actors i configured my resource like these code, but when i see the user_id in Version with Ash.read all of them is nil
paper_trail do
primary_key_type :uuid_v7
change_tracking_mode(:snapshot)
store_action_name?(true)
store_action_inputs?(true)
ignore_attributes([:inserted_at, :updated_at, :archived_at])
ignore_actions [:unarchive, :permanent_destroy]
attributes_as_attributes([:site_id])
create_version_on_destroy?(true)
only_when_changed?(true)
relationship_opts(public?: true)
belongs_to_actor(:user, MishkaCms.Accounts.User, domain: MishkaCms.Accounts)
mixin({MishkaCms.Runtime.Resources.Mixins.LayoutPaperTrailMixin, :postgres, []})
end
paper_trail do
primary_key_type :uuid_v7
change_tracking_mode(:snapshot)
store_action_name?(true)
store_action_inputs?(true)
ignore_attributes([:inserted_at, :updated_at, :archived_at])
ignore_actions [:unarchive, :permanent_destroy]
attributes_as_attributes([:site_id])
create_version_on_destroy?(true)
only_when_changed?(true)
relationship_opts(public?: true)
belongs_to_actor(:user, MishkaCms.Accounts.User, domain: MishkaCms.Accounts)
mixin({MishkaCms.Runtime.Resources.Mixins.LayoutPaperTrailMixin, :postgres, []})
end
and my mixin is
def postgres do
quote do
postgres do
table "layout_versions"
repo MishkaCms.Repo

references do
reference :version_source, on_delete: :delete
end
end

actions do
read :get_any do
get? true
multitenancy :bypass
end
end
end
end
def postgres do
quote do
postgres do
table "layout_versions"
repo MishkaCms.Repo

references do
reference :version_source, on_delete: :delete
end
end

actions do
read :get_any do
get? true
multitenancy :bypass
end
end
end
end
Update for Example:
fresh_layout = Ash.get!(MishkaCms.Runtime.Layout, layout_id, action: :get_any, authorize?: false)

fresh_layout
|> Ash.Changeset.for_update(:update, %{
description: "Simple main layout with navigation V#{item}"
})
|> Ash.update!(tenant: site.id, actor: none_user)
fresh_layout = Ash.get!(MishkaCms.Runtime.Layout, layout_id, action: :get_any, authorize?: false)

fresh_layout
|> Ash.Changeset.for_update(:update, %{
description: "Simple main layout with navigation V#{item}"
})
|> Ash.update!(tenant: site.id, actor: none_user)
It has extra config i did not inside my code? Thank you in advance
6 Replies
sevenseacat
sevenseacat•2w ago
so what's none_user and what does the generated version look like when you read it?
Shahryar
ShahryarOP•2w ago
Hi @Rebecca It is none user, i use simple get
none_user =
MishkaCms.Accounts.User
|> Ash.Query.filter(email == "none@example.com")
|> Ash.read_one!(authorize?: false)
none_user =
MishkaCms.Accounts.User
|> Ash.Query.filter(email == "none@example.com")
|> Ash.read_one!(authorize?: false)
Version output:
%MishkaCms.Runtime.Layout.Version{
id: "0199762d-6648-7288-a854-33803d8799cf",
version_action_type: :create,
version_action_name: :create,
version_action_inputs: %{...},
site_id: "0e078349-517c-40ca-96fa-da0f0156a7c1",
version_source_id: "2cc4f20c-7d19-42bd-af15-458ad66b16da",
changes: %{...}
},
version_inserted_at: ~U[2025-09-23 10:45:10.856184Z],
version_updated_at: ~U[2025-09-23 10:45:10.856184Z],
user_id: nil,
version_source: #Ash.NotLoaded<:relationship, field: :version_source>,
user: #Ash.NotLoaded<:relationship, field: :user>,
__meta__: #Ecto.Schema.Metadata<:loaded, "layout_versions">
}
]}
%MishkaCms.Runtime.Layout.Version{
id: "0199762d-6648-7288-a854-33803d8799cf",
version_action_type: :create,
version_action_name: :create,
version_action_inputs: %{...},
site_id: "0e078349-517c-40ca-96fa-da0f0156a7c1",
version_source_id: "2cc4f20c-7d19-42bd-af15-458ad66b16da",
changes: %{...}
},
version_inserted_at: ~U[2025-09-23 10:45:10.856184Z],
version_updated_at: ~U[2025-09-23 10:45:10.856184Z],
user_id: nil,
version_source: #Ash.NotLoaded<:relationship, field: :version_source>,
user: #Ash.NotLoaded<:relationship, field: :user>,
__meta__: #Ecto.Schema.Metadata<:loaded, "layout_versions">
}
]}
full output: https://gist.github.com/shahryarjb/0543de98c2c71f9b60ca61a05530f5a0
sevenseacat
sevenseacat•2w ago
I'm wondering if its an authorization issue
Shahryar
ShahryarOP•2w ago
it lets Record changed, but dose not allow it to put user id inside the field? and even with authorize?: false ?
sevenseacat
sevenseacat•2w ago
you're not using authorize?: false when creating the version record. I think I remember seeing something like this, where you need users to be able to read their own records to be able to relate them
Shahryar
ShahryarOP•2w ago
i tested with this too
fresh_layout = Ash.get!(MishkaCms.Runtime.Layout, layout_id, action: :get_any, authorize?: false)

fresh_layout
|> Ash.Changeset.for_update(:update, %{
description: "Simple main layout with navigation V#{item}"
})
|> Ash.update!(tenant: site.id, actor: none_user, authorize?: false)
fresh_layout = Ash.get!(MishkaCms.Runtime.Layout, layout_id, action: :get_any, authorize?: false)

fresh_layout
|> Ash.Changeset.for_update(:update, %{
description: "Simple main layout with navigation V#{item}"
})
|> Ash.update!(tenant: site.id, actor: none_user, authorize?: false)
but it is not diffrent, both of them user_id is nil inside Version! I have no idea about it why! 🥲

Did you find this page helpful?