Correct way to pass authorization information to query in a custom change?

I want to delete some old records in the custom change.
Is this the right way to pass authorization information:
defmodule MyApp.Changes.RemoveOldRecords do
use Ash.Resource.Change

require Logger

@impl true
def change(changeset, opts, context) do
# ===============>
query_context = %{
actor: context.actor,
authorize?: context.authorize?,
tenant: context.tenant
}

MyApp.Record
|> Ash.Query.filter(date < ^Date.utc_today())
|> Ash.Query.set_context(query_context) # <==================
|> Ash.bulk_destroy(:destroy, %{})
|> case do
%Ash.BulkResult{error_count: error_count, errors: errors, records: records} ->
if error_count > 0 or (not is_nil(errors) and length(errors) > 0) do
Logger.error("Failed to remove old records: #{inspect(errors)}")
else
Logger.info("Removed #{length(records)} old records")
end
end

changeset
end
end
defmodule MyApp.Changes.RemoveOldRecords do
use Ash.Resource.Change

require Logger

@impl true
def change(changeset, opts, context) do
# ===============>
query_context = %{
actor: context.actor,
authorize?: context.authorize?,
tenant: context.tenant
}

MyApp.Record
|> Ash.Query.filter(date < ^Date.utc_today())
|> Ash.Query.set_context(query_context) # <==================
|> Ash.bulk_destroy(:destroy, %{})
|> case do
%Ash.BulkResult{error_count: error_count, errors: errors, records: records} ->
if error_count > 0 or (not is_nil(errors) and length(errors) > 0) do
Logger.error("Failed to remove old records: #{inspect(errors)}")
else
Logger.info("Removed #{length(records)} old records")
end
end

changeset
end
end
Solution:
The best way is to use the scope option, and pass the callback's context as the scope
Jump to solution
3 Replies
Cooky
CookyOP5w ago
The above code caused runtime error. This seems to work:
# |> Ash.Query.set_context(query_context)
|> Ash.bulk_destroy!(:destroy, %{}, query_context)
# |> Ash.Query.set_context(query_context)
|> Ash.bulk_destroy!(:destroy, %{}, query_context)
Solution
ZachDaniel
ZachDaniel5w ago
The best way is to use the scope option, and pass the callback's context as the scope
ZachDaniel
ZachDaniel5w ago
|> Ash.bulk_destroy!(:destroy, %{}, scope: context)
|> Ash.bulk_destroy!(:destroy, %{}, scope: context)

Did you find this page helpful?