@@ -13,15 +13,16 @@ defmodule AshStorage.Changes.Attach do
1313 end
1414
1515 @ impl true
16- def change ( changeset , opts , _context ) do
16+ def change ( changeset , opts , context ) do
1717 attachment_name = opts [ :attachment_name ]
18+ context_opts = Ash.Context . to_opts ( context )
1819
1920 changeset
2021 |> Ash.Changeset . before_action ( fn changeset ->
2122 record = changeset . data
2223 resource = record . __struct__
2324
24- case do_attach ( record , resource , attachment_name , changeset ) do
25+ case do_attach ( record , resource , attachment_name , changeset , context_opts ) do
2526 { :ok , attrs_to_write , attach_context } ->
2627 changeset
2728 |> Ash.Changeset . force_change_attributes ( attrs_to_write )
@@ -33,15 +34,22 @@ defmodule AshStorage.Changes.Attach do
3334 end )
3435 |> Ash.Changeset . after_action ( fn changeset , record ->
3536 case changeset . context [ :__ash_storage_attach__ ] do
36- % { blob: blob , attachment_def: attachment_def , service_mod: service_mod , ctx: ctx } =
37- context ->
37+ % {
38+ blob: blob ,
39+ attachment_def: attachment_def ,
40+ service_mod: service_mod ,
41+ ctx: ctx ,
42+ context_opts: context_opts
43+ } = attach_context ->
3844 resource = record . __struct__
3945
40- with { :ok , _ } <- maybe_replace_existing ( record , attachment_def , service_mod , ctx ) ,
41- { :ok , attachment } <- create_attachment ( record , attachment_def , blob ) ,
46+ with { :ok , _ } <-
47+ maybe_replace_existing ( record , attachment_def , service_mod , ctx , context_opts ) ,
48+ { :ok , attachment } <-
49+ create_attachment ( record , attachment_def , blob , context_opts ) ,
4250 :ok <- run_eager_variants ( blob , attachment_def , resource ) ,
4351 { :ok , blob } <- store_oban_variants ( blob , attachment_def , resource ) do
44- if context [ :has_oban_analyzers? ] do
52+ if attach_context [ :has_oban_analyzers? ] do
4553 AshOban . run_trigger ( blob , :run_pending_analyzers )
4654 end
4755
@@ -63,7 +71,7 @@ defmodule AshStorage.Changes.Attach do
6371 end )
6472 end
6573
66- defp do_attach ( record , resource , attachment_name , changeset ) do
74+ defp do_attach ( record , resource , attachment_name , changeset , context_opts ) do
6775 io = Ash.Changeset . get_argument ( changeset , :io )
6876 filename = Ash.Changeset . get_argument ( changeset , :filename )
6977
@@ -77,7 +85,7 @@ defmodule AshStorage.Changes.Attach do
7785 ctx = build_context ( service_opts , resource , attachment_def , changeset )
7886
7987 with { :ok , blob } <-
80- upload_and_create_blob ( resource , service_mod , ctx , io ,
88+ upload_and_create_blob ( resource , service_mod , ctx , io , context_opts ,
8189 filename: filename ,
8290 content_type: content_type ,
8391 metadata: metadata
@@ -89,6 +97,7 @@ defmodule AshStorage.Changes.Attach do
8997 attachment_def: attachment_def ,
9098 service_mod: service_mod ,
9199 ctx: ctx ,
100+ context_opts: context_opts ,
92101 has_oban_analyzers?: has_oban_analyzers? ( attachment_def )
93102 } }
94103 end
@@ -234,7 +243,7 @@ defmodule AshStorage.Changes.Attach do
234243 end
235244 end
236245
237- defp upload_and_create_blob ( resource , service_mod , ctx , io , opts ) do
246+ defp upload_and_create_blob ( resource , service_mod , ctx , io , context_opts , opts ) do
238247 filename = Keyword . fetch! ( opts , :filename )
239248 content_type = Keyword . get ( opts , :content_type , "application/octet-stream" )
240249 metadata = Keyword . get ( opts , :metadata , % { } )
@@ -244,11 +253,10 @@ defmodule AshStorage.Changes.Attach do
244253 checksum = :crypto . hash ( :md5 , data ) |> Base . encode64 ( )
245254 byte_size = byte_size ( data )
246255
247- with :ok <- service_mod . upload ( key , data , ctx ) do
256+ with { :ok , extra_blob_attrs } <- normalize_upload ( service_mod . upload ( key , data , ctx ) ) do
248257 blob_resource = Info . storage_blob_resource! ( resource )
249258
250- Ash . create (
251- blob_resource ,
259+ blob_attrs =
252260 % {
253261 key: key ,
254262 filename: filename ,
@@ -258,12 +266,17 @@ defmodule AshStorage.Changes.Attach do
258266 service_name: service_mod ,
259267 service_opts: persistable_service_opts ( service_mod , ctx . service_opts ) ,
260268 metadata: metadata
261- } ,
262- action: :create
263- )
269+ }
270+ |> Map . merge ( extra_blob_attrs )
271+
272+ Ash . create ( blob_resource , blob_attrs , Keyword . merge ( context_opts , action: :create ) )
264273 end
265274 end
266275
276+ defp normalize_upload ( :ok ) , do: { :ok , % { } }
277+ defp normalize_upload ( { :ok , attrs } ) when is_map ( attrs ) , do: { :ok , attrs }
278+ defp normalize_upload ( { :error , _ } = error ) , do: error
279+
267280 # -- IO helpers --
268281
269282 defp read_io ( % Ash.Type.File { } = file ) do
@@ -325,17 +338,24 @@ defmodule AshStorage.Changes.Attach do
325338 # -- Attachment helpers --
326339
327340 # sobelow_skip ["DOS.BinToAtom"]
328- defp maybe_replace_existing ( record , % { type: :one } = attachment_def , service_mod , ctx ) do
329- case find_attachments ( record , attachment_def ) do
341+ defp maybe_replace_existing (
342+ record ,
343+ % { type: :one } = attachment_def ,
344+ service_mod ,
345+ ctx ,
346+ context_opts
347+ ) do
348+ case find_attachments ( record , attachment_def , context_opts ) do
330349 { :ok , [ ] } -> { :ok , :noop }
331- { :ok , existing } -> purge_attachments ( existing , service_mod , ctx )
350+ { :ok , existing } -> purge_attachments ( existing , service_mod , ctx , context_opts )
332351 end
333352 end
334353
335- defp maybe_replace_existing ( _record , % { type: :many } , _service_mod , _ctx ) , do: { :ok , :noop }
354+ defp maybe_replace_existing ( _record , % { type: :many } , _service_mod , _ctx , _context_opts ) ,
355+ do: { :ok , :noop }
336356
337357 # sobelow_skip ["DOS.BinToAtom"]
338- defp create_attachment ( record , attachment_def , blob ) do
358+ defp create_attachment ( record , attachment_def , blob , context_opts ) do
339359 resource = record . __struct__
340360 attachment_resource = Info . storage_attachment_resource! ( resource )
341361
@@ -367,11 +387,11 @@ defmodule AshStorage.Changes.Attach do
367387 }
368388 end
369389
370- Ash . create ( attachment_resource , params , action: :create )
390+ Ash . create ( attachment_resource , params , Keyword . merge ( context_opts , action: :create ) )
371391 end
372392
373393 # sobelow_skip ["DOS.BinToAtom"]
374- defp find_attachments ( record , attachment_def ) do
394+ defp find_attachments ( record , attachment_def , context_opts ) do
375395 resource = record . __struct__
376396 attachment_resource = Info . storage_attachment_resource! ( resource )
377397 record_id = Map . get ( record , :id ) |> to_string ( )
@@ -398,16 +418,19 @@ defmodule AshStorage.Changes.Attach do
398418 attachment_resource
399419 |> Ash.Query . filter ( ^ filter )
400420 |> Ash.Query . load ( :blob )
421+ |> Ash.Query . set_tenant ( context_opts [ :tenant ] )
401422 |> Ash . read ( )
402423 end
403424
404- defp purge_attachments ( attachments , service_mod , ctx ) do
425+ defp purge_attachments ( attachments , service_mod , ctx , context_opts ) do
426+ destroy_opts = Keyword . merge ( context_opts , action: :destroy , return_destroyed?: true )
427+
405428 Enum . reduce_while ( attachments , { :ok , [ ] } , fn att , { :ok , acc } ->
406429 blob = att . blob
407430
408431 with :ok <- service_mod . delete ( blob . key , ctx ) ,
409- { :ok , _ } <- Ash . destroy ( att , action: :destroy , return_destroyed?: true ) ,
410- { :ok , _ } <- Ash . destroy ( blob , action: :destroy , return_destroyed?: true ) do
432+ { :ok , _ } <- Ash . destroy ( att , destroy_opts ) ,
433+ { :ok , _ } <- Ash . destroy ( blob , destroy_opts ) do
411434 { :cont , { :ok , [ att | acc ] } }
412435 else
413436 { :error , error } -> { :halt , { :error , error } }
0 commit comments