File tree Expand file tree Collapse file tree
lib/ash_backpex/live_resource/transformers Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -408,6 +408,25 @@ defmodule AshBackpex.LiveResource.Transformers.GenerateBackpex do
408408 def can? ( _assigns , :delete , _item ) , do: false
409409 end
410410
411+ # Fallback for custom item actions and any other actions
412+ # Checks Ash authorization if a matching action exists, otherwise allows by default
413+ def can? ( assigns , action , item ) do
414+ case Ash.Resource.Info . action ( @ resource , action ) do
415+ nil ->
416+ true
417+
418+ ash_action ->
419+ target =
420+ if is_struct ( item ) and item . __struct__ == @ resource do
421+ { item , ash_action . name }
422+ else
423+ { @ resource , ash_action . name }
424+ end
425+
426+ Ash . can? ( target , Map . get ( assigns , :current_user ) )
427+ end
428+ end
429+
411430 def maybe_default_options ( assigns ) do
412431 case assigns do
413432 % { field: { attribute_name , _field_cfg } } ->
Original file line number Diff line number Diff line change @@ -41,6 +41,20 @@ defmodule AshBackpex.AuthzTest do
4141 end
4242 end
4343
44+ describe "AshBackpex.LiveResource :: can? with custom item actions" do
45+ test "returns true for unknown actions that don't exist on the resource" do
46+ # :promote is not an Ash action on Item, so fallback returns true
47+ assert TestCustomItemActionLive . can? ( % { current_user: nil } , :promote , % { } )
48+ assert TestCustomItemActionLive . can? ( % { current_user: nil } , :some_unknown_action , % { } )
49+ end
50+
51+ test "checks Ash authorization when action exists on resource" do
52+ # :read exists on Item resource, so it checks Ash.can?
53+ # Item has no policies, so it should return true
54+ assert TestCustomItemActionLive . can? ( % { current_user: nil } , :read , % { } )
55+ end
56+ end
57+
4458 describe "AshBackpex.Adapter :: it can" do
4559 test "list/3" do
4660 user = user ( )
Original file line number Diff line number Diff line change @@ -113,3 +113,46 @@ defmodule TestLayout do
113113 """
114114 end
115115end
116+
117+ # Custom item action for testing can?/3 fallback
118+ defmodule TestPromoteItemAction do
119+ @ moduledoc false
120+ use BackpexWeb , :item_action
121+
122+ @ impl Backpex.ItemAction
123+ def icon ( assigns , _item ) do
124+ ~H"""
125+ < Backpex.HTML.CoreComponents . icon
126+ name = "hero-arrow-up-circle "
127+ class = "h-5 w-5 cursor-pointer transition duration-75 hover:scale-110 hover:text-success "
128+ />
129+ """
130+ end
131+
132+ @ impl Backpex.ItemAction
133+ def label ( _assigns , _item ) , do: "Promote"
134+
135+ @ impl Backpex.ItemAction
136+ def handle ( socket , _items , _data ) do
137+ { :ok , socket }
138+ end
139+ end
140+
141+ # LiveResource with custom item action for testing can?/3 fallback
142+ defmodule TestCustomItemActionLive do
143+ @ moduledoc false
144+ use AshBackpex.LiveResource
145+
146+ backpex do
147+ resource ( AshBackpex.TestDomain.Item )
148+ layout ( { TestLayout , :admin } )
149+
150+ item_actions do
151+ action :promote , TestPromoteItemAction
152+ end
153+
154+ fields do
155+ field ( :name )
156+ end
157+ end
158+ end
You can’t perform that action at this time.
0 commit comments