17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
# File 'app/services/collavre/tools/creative_attach_files_service.rb', line 17
def call(creative_id:, file_paths:)
raise "Current.user is required" unless Current.user
creative = Creative.find_by(id: creative_id)
return { error: "Creative not found", id: creative_id } unless creative
unless creative.has_permission?(Current.user, :write)
return { error: "No write permission on Creative", id: creative_id }
end
root = self.class.upload_root
resolved = []
missing = []
outside = []
file_paths.each do |raw|
begin
real = File.realpath(raw)
rescue Errno::ENOENT, Errno::ENOTDIR, Errno::EACCES
missing << raw
next
end
unless File.file?(real)
missing << raw
next
end
if path_under?(real, root)
resolved << real
else
outside << raw
end
end
return { error: "Missing files", missing: missing } if missing.any?
return { error: "Files outside upload root", upload_root: root.to_s, outside: outside } if outside.any?
attached = []
ActiveRecord::Base.transaction do
resolved.each do |path|
File.open(path, "rb") do |io|
creative.files.attach(
io: io,
filename: File.basename(path),
content_type: Marcel::MimeType.for(Pathname.new(path)) || "application/octet-stream"
)
end
end
creative.save!
attached = creative.files.last(resolved.length)
end
{
success: true,
creative_id: creative.id,
attachments: attached.map { |a|
{
signed_id: a.blob.signed_id,
filename: a.filename.to_s,
content_type: a.content_type,
byte_size: a.byte_size,
url: public_asset_url(a.blob)
}
}
}
end
|