@@ -12,37 +12,45 @@ defmodule Upload.Multi do
12
12
13
13
@ doc """
14
14
Upload a blob to storage.
15
+
16
+ ## Options
17
+
18
+ - `canned_acl` - The canned ACL to use with S3 if using S3 as the storage
19
+ backend.
20
+
15
21
"""
16
- @ spec upload_blob ( Multi . t ( ) , Multi . name ( ) , Blob . t ( ) ) :: Multi . t ( )
17
- def upload_blob ( multi , name , % Blob { key: key , path: path } = blob )
18
- when is_binary ( key ) and is_binary ( path ) do
19
- Multi . run ( multi , name , fn _repo , _ctx -> do_upload_blob ( blob ) end )
20
- end
22
+ def upload_blob ( multi , name , blob , opts \\ [ ] )
21
23
22
24
@ spec upload_blob ( Multi . t ( ) , Multi . name ( ) , Blob . t ( ) ) :: Multi . t ( )
23
- def upload_blob ( multi , name , % Blob { key: key , path: path } = blob )
25
+ def upload_blob ( multi , name , % Blob { key: key , path: path } = blob , opts )
24
26
when is_binary ( key ) and is_binary ( path ) do
25
- Multi . run ( multi , name , fn _repo , _ctx -> do_upload_blob ( blob ) end )
27
+ Multi . run ( multi , name , fn _repo , _ctx -> do_upload_blob ( blob , opts ) end )
26
28
end
27
29
28
30
@ spec upload_blob ( Multi . t ( ) , Multi . name ( ) , Multi . fun ( Blob . t ( ) ) ) :: Multi . t ( )
29
- def upload_blob ( multi , name , fun ) when is_function ( fun ) do
30
- Multi . run ( multi , name , fn _repo , ctx -> ctx |> fun . ( ) |> do_upload_blob ( ) end )
31
+ def upload_blob ( multi , name , fun , opts ) when is_function ( fun ) do
32
+ Multi . run ( multi , name , fn _repo , ctx -> ctx |> fun . ( ) |> do_upload_blob ( opts ) end )
31
33
end
32
34
33
- defp do_upload_blob ( nil ) , do: { :ok , nil }
34
- defp do_upload_blob ( % NotLoaded { } = blob ) , do: { :ok , blob }
35
- defp do_upload_blob ( % Blob { path: nil } = blob ) , do: { :ok , blob }
35
+ defp do_upload_blob ( nil , _opts ) , do: { :ok , nil }
36
+ defp do_upload_blob ( % NotLoaded { } = blob , _opts ) , do: { :ok , blob }
37
+ defp do_upload_blob ( % Blob { path: nil } = blob , _opts ) , do: { :ok , blob }
36
38
37
- defp do_upload_blob ( % Blob { path: path , key: key } = blob ) when is_binary ( key ) do
39
+ defp do_upload_blob ( % Blob { path: path , key: key } = blob , opts ) when is_binary ( key ) do
38
40
Upload.Logger . info ( "Uploading #{ key } " )
39
41
40
42
with :ok <- Storage . upload ( path , key ) ,
43
+ :ok <- Upload . put_access_control_list ( blob , opts [ :canned_acl ] || :private ) ,
41
44
do: { :ok , blob }
42
45
end
43
46
44
47
@ doc """
45
48
Upload multiple variants as part of an `Ecto.Multi`.
49
+
50
+ ## Options
51
+
52
+ - `canned_acl` - The canned ACL to use with S3 if using S3 as the storage
53
+ backend.
46
54
"""
47
55
def upload_variants ( multi , name , fun , variants , transform_fn , opts \\ [ ] )
48
56
when is_function ( fun ) do
@@ -70,7 +78,8 @@ defmodule Upload.Multi do
70
78
71
79
If the `field` change is `nil` in the changeset, it will be deleted remotely
72
80
and in your database. If the `field` change in the changeset is an uploadable
73
- type such as a `Plug.Upload` or file path, it will be uploaded.
81
+ type such as a `Plug.Upload` or file path, it will be uploaded, replacing any
82
+ existing associated upload.
74
83
75
84
## Example
76
85
@@ -82,6 +91,11 @@ defmodule Upload.Multi do
82
91
|> Repo.transaction()
83
92
end
84
93
```
94
+
95
+ ## Options
96
+
97
+ - `canned_acl` - The canned ACL to use with S3 if using S3 as the storage
98
+ backend.
85
99
"""
86
100
def handle_changes ( multi , name , subject , changeset , field , opts \\ [ ] ) do
87
101
key_function = key_function_from_opts ( opts )
@@ -110,7 +124,7 @@ defmodule Upload.Multi do
110
124
record_changeset . changes
111
125
|> Enum . reduce ( Ecto.Multi . new ( ) , fn { changed_field , change } , multi ->
112
126
# Deletes if the change is 'nil', uploads otherwise.
113
- handle_change ( { changed_field , change } , multi , changeset )
127
+ handle_change ( { changed_field , change } , multi , changeset , opts )
114
128
end )
115
129
|> Multi . update ( "#{ field } _attach_blob" , record_changeset )
116
130
|> repo . transaction ( )
@@ -137,7 +151,7 @@ defmodule Upload.Multi do
137
151
138
152
# We're setting the upload field to nil so let's check
139
153
# if the existing field is set and delete it if so.
140
- defp handle_change ( { field , nil } , multi , changeset ) do
154
+ defp handle_change ( { field , nil } , multi , changeset , _opts ) do
141
155
case Map . get ( changeset . data , field ) do
142
156
% Upload.Blob { } = blob -> delete_blob ( multi , :delete_blob , blob )
143
157
_ -> multi
@@ -146,12 +160,12 @@ defmodule Upload.Multi do
146
160
147
161
# We're setting the upload field so let's check
148
162
# if the existing field is set and delete it if so.
149
- defp handle_change ( { field , change } , multi , changeset ) do
150
- multi = handle_change ( { field , nil } , multi , changeset )
163
+ defp handle_change ( { field , change } , multi , changeset , opts ) do
164
+ multi = handle_change ( { field , nil } , multi , changeset , opts )
151
165
152
166
blob = Ecto.Changeset . apply_changes ( change )
153
167
154
- upload_blob ( multi , field , blob )
168
+ upload_blob ( multi , field , blob , opts )
155
169
end
156
170
157
171
@ doc """
@@ -221,12 +235,20 @@ defmodule Upload.Multi do
221
235
@ doc """
222
236
Creates and uploads a single variant of an `Upload.Blob` inside of an `Ecto.Multi`.
223
237
238
+ ## Example
239
+
224
240
```elixir
225
241
Ecto.Multi.new()
226
242
|> Ecto.Multi.insert(:person, changeset)
227
243
|> Upload.Multi.handle_changes(:upload_avatar, :person, changeset, :avatar, key_function: key_function)
228
244
|> Upload.Multi.create_variant(fn ctx -> ctx.person.avatar end, :small, transform_fn: &transform_fn/3)
229
245
```
246
+
247
+ ## Options
248
+
249
+ - `canned_acl` - The canned ACL to use with S3 if using S3 as the storage
250
+ backend.
251
+
230
252
"""
231
253
def create_variant ( multi , fun , variant , transform_fn , opts )
232
254
when is_function ( fun , 1 ) and is_function ( transform_fn , 3 ) do
@@ -257,7 +279,8 @@ defmodule Upload.Multi do
257
279
original_blob ,
258
280
variant ,
259
281
transform_fn ,
260
- format
282
+ format ,
283
+ opts
261
284
)
262
285
end )
263
286
end
@@ -267,12 +290,19 @@ defmodule Upload.Multi do
267
290
@ doc """
268
291
Creates and uploads multiple variants of an `Upload.Blob` inside of an `Ecto.Multi`.
269
292
293
+ ## Example
294
+
270
295
```elixir
271
296
Ecto.Multi.new()
272
297
|> Ecto.Multi.insert(:person, changeset)
273
298
|> Upload.Multi.handle_changes(:upload_avatar, :person, changeset, :avatar, key_function: key_function)
274
299
|> Upload.Multi.create_variants(fn ctx -> ctx.person.avatar end, [:small, :large], transform_fn: &transform_fn/3)
275
300
```
301
+
302
+ ## Options
303
+
304
+ - `canned_acl` - The canned ACL to use with S3 if using S3 as the storage
305
+ backend.
276
306
"""
277
307
def create_variants ( multi , fun , variants , transform_fn , opts )
278
308
when is_function ( fun , 1 ) and is_function ( transform_fn , 3 ) do
@@ -305,21 +335,29 @@ defmodule Upload.Multi do
305
335
original_blob ,
306
336
variant ,
307
337
transform_fn ,
308
- format
338
+ format ,
339
+ opts
309
340
)
310
341
end )
311
342
end )
312
343
end
313
344
314
- defp download_and_insert_variant ( multi , original_blob , variant , transform_fn , format ) do
345
+ defp download_and_insert_variant (
346
+ multi ,
347
+ original_blob ,
348
+ variant ,
349
+ transform_fn ,
350
+ format ,
351
+ opts
352
+ ) do
315
353
Multi . run ( multi , "download_and_insert_#{ variant } _#{ format } " , fn repo , _ ->
316
354
with { :ok , blob_path } <- create_random_file ( ) ,
317
355
:ok <- download_file ( original_blob . key , blob_path ) ,
318
356
{ :ok , variant_path } <-
319
357
call_transform_fn ( transform_fn , blob_path , variant , format ) ,
320
358
:ok <- cleanup ( blob_path ) ,
321
359
{ :ok , blob } <- insert_variant ( repo , original_blob , variant , variant_path ) ,
322
- { :ok , _ } <- do_upload_blob ( blob ) ,
360
+ { :ok , _ } <- do_upload_blob ( blob , opts ) ,
323
361
:ok <- cleanup ( variant_path ) do
324
362
{ :ok , blob }
325
363
else
0 commit comments