Skip to content

Commit 5d1b6a5

Browse files
committed
fix: authorize before before_transaction hooks in bulk actions
1 parent d81ccf0 commit 5d1b6a5

File tree

4 files changed

+106
-10
lines changed

4 files changed

+106
-10
lines changed

lib/ash/actions/create/bulk.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,7 @@ defmodule Ash.Actions.Create.Bulk do
501501
changeset.action.require_attributes
502502
)
503503
end)
504+
|> authorize(opts)
504505
|> Ash.Actions.Helpers.split_and_run_simple(
505506
action,
506507
opts,
@@ -645,9 +646,8 @@ defmodule Ash.Actions.Create.Bulk do
645646
end)
646647

647648
batch =
648-
batch
649-
|> authorize(opts)
650-
|> Ash.Actions.Update.Bulk.run_bulk_before_batches(
649+
Ash.Actions.Update.Bulk.run_bulk_before_batches(
650+
batch,
651651
changes,
652652
all_changes,
653653
opts,

lib/ash/actions/destroy/bulk.ex

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,6 +1433,8 @@ defmodule Ash.Actions.Destroy.Bulk do
14331433
:bulk_destroy
14341434
)
14351435

1436+
batch = authorize(batch, opts)
1437+
14361438
batch =
14371439
if re_sort? do
14381440
Enum.sort_by(batch, & &1.context.bulk_destroy.index)
@@ -1611,10 +1613,8 @@ defmodule Ash.Actions.Destroy.Bulk do
16111613
end)
16121614

16131615
batch =
1614-
batch
1615-
|> authorize(opts)
1616-
|> Enum.to_list()
1617-
|> Ash.Actions.Update.Bulk.run_bulk_before_batches(
1616+
Ash.Actions.Update.Bulk.run_bulk_before_batches(
1617+
batch,
16181618
changes,
16191619
all_changes,
16201620
opts,

lib/ash/actions/update/bulk.ex

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1751,6 +1751,8 @@ defmodule Ash.Actions.Update.Bulk do
17511751
context_key
17521752
)
17531753

1754+
batch = authorize(batch, opts)
1755+
17541756
batch =
17551757
if re_sort? do
17561758
Enum.sort_by(batch, & &1.context[context_key].index)
@@ -1920,9 +1922,8 @@ defmodule Ash.Actions.Update.Bulk do
19201922
end)
19211923

19221924
batch =
1923-
batch
1924-
|> authorize(opts)
1925-
|> run_bulk_before_batches(
1925+
run_bulk_before_batches(
1926+
batch,
19261927
changes,
19271928
all_changes,
19281929
opts,

test/policy/simple_test.exs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,4 +654,99 @@ defmodule Ash.Test.Policy.SimpleTest do
654654

655655
assert user2_got_thing.id == user2_thing.id
656656
end
657+
658+
defmodule ResourceWithBeforeTransactionHook do
659+
use Ash.Resource,
660+
domain: Ash.Test.Domain,
661+
authorizers: [Ash.Policy.Authorizer]
662+
663+
attributes do
664+
uuid_primary_key :id
665+
attribute :name, :string, public?: true
666+
end
667+
668+
actions do
669+
defaults [:read]
670+
671+
create :create do
672+
primary? true
673+
accept [:name]
674+
end
675+
676+
update :test_action_with_after_transaction do
677+
accept [:name]
678+
679+
change before_transaction(fn changeset, _context ->
680+
raise "running before transaction"
681+
end)
682+
683+
change after_transaction(fn _changeset, res, _context ->
684+
res
685+
end)
686+
687+
require_atomic? false
688+
end
689+
690+
update :test_action_without_after_transaction do
691+
accept [:name]
692+
693+
change before_transaction(fn changeset, _context ->
694+
raise "running before transaction"
695+
end)
696+
697+
require_atomic? false
698+
end
699+
end
700+
701+
policies do
702+
policy action_type(:read) do
703+
authorize_if always()
704+
end
705+
706+
policy action_type(:create) do
707+
authorize_if always()
708+
end
709+
end
710+
end
711+
712+
test "before_transaction hook should not run when action is not authorized via bulk_update" do
713+
record = Ash.create!(ResourceWithBeforeTransactionHook, %{name: "test"}, authorize?: false)
714+
715+
query =
716+
ResourceWithBeforeTransactionHook
717+
|> Ash.DataLayer.Simple.set_data([record])
718+
|> Ash.Query.limit(1)
719+
720+
assert_raise Ash.Error.Forbidden, fn ->
721+
Ash.bulk_update!(query, :test_action_with_after_transaction, %{},
722+
return_errors?: true,
723+
notify?: true,
724+
strategy: [:atomic, :stream, :atomic_batches],
725+
allow_stream_with: :full_read,
726+
authorize_changeset_with: :filter,
727+
return_records?: true,
728+
authorize?: true,
729+
read_action: :read,
730+
domain: Ash.Test.Domain,
731+
select: [],
732+
load: []
733+
)
734+
end
735+
736+
assert_raise Ash.Error.Forbidden, fn ->
737+
Ash.bulk_update!(query, :test_action_without_after_transaction, %{},
738+
return_errors?: true,
739+
notify?: true,
740+
strategy: [:atomic, :stream, :atomic_batches],
741+
allow_stream_with: :full_read,
742+
authorize_changeset_with: :filter,
743+
return_records?: true,
744+
authorize?: true,
745+
read_action: :read,
746+
domain: Ash.Test.Domain,
747+
select: [],
748+
load: []
749+
)
750+
end
751+
end
657752
end

0 commit comments

Comments
 (0)