Do not use ActiveStorage variants, process original avatar
Variants are currently broken. So we process the original file with the most common avatar dimensions and stripping metadata, then hash and upload only that version.
This commit is contained in:
@@ -5,22 +5,20 @@ class AvatarsController < ApplicationController
|
||||
|
||||
sha256_hash = params[:hash]
|
||||
format = params[:format]&.to_sym || :png
|
||||
size = params[:size]&.to_sym || :original
|
||||
# size = params[:size]&.to_sym || :original
|
||||
|
||||
unless user.avatar.filename.to_s == "#{sha256_hash}.#{format}"
|
||||
http_status :not_found and return
|
||||
end
|
||||
|
||||
blob = if size == :original
|
||||
user.avatar.blob
|
||||
else
|
||||
# TODO Variants use the same custom storage key/path, which
|
||||
# makes blob downloads always fetch the original version instead
|
||||
# of the variant. Needs to be fixed/added in Rails.
|
||||
user.avatar_variant(size: size)&.blob
|
||||
end
|
||||
# TODO See note for avatar_variant in user model
|
||||
# blob = if size == :original
|
||||
# user.avatar.blob
|
||||
# else
|
||||
# user.avatar_variant(size: size)&.blob
|
||||
# end
|
||||
|
||||
data = blob.download
|
||||
data = user.avatar.blob.download
|
||||
send_data data, type: "image/#{format}", disposition: "inline"
|
||||
else
|
||||
http_status :not_found
|
||||
|
||||
@@ -191,9 +191,14 @@ class SettingsController < ApplicationController
|
||||
end
|
||||
|
||||
def store_user_avatar
|
||||
data = @user.avatar_new.tempfile.read
|
||||
@user.avatar_new.tempfile.rewind
|
||||
hash = Digest::SHA256.hexdigest(data)
|
||||
io = @user.avatar_new.tempfile
|
||||
img_data = process_avatar(io)
|
||||
tempfile = Tempfile.create
|
||||
tempfile.binmode
|
||||
tempfile.write(img_data)
|
||||
tempfile.rewind
|
||||
|
||||
hash = Digest::SHA256.hexdigest(img_data)
|
||||
ext = @user.avatar_new.content_type == "image/png" ? "png" : "jpg"
|
||||
filename = "#{hash}.#{ext}"
|
||||
|
||||
@@ -202,8 +207,22 @@ class SettingsController < ApplicationController
|
||||
false
|
||||
else
|
||||
key = "users/#{@user.cn}/avatars/#{filename}"
|
||||
@user.avatar.attach io: @user.avatar_new.tempfile, key: key, filename: filename
|
||||
@user.avatar.attach io: tempfile, key: key, filename: filename
|
||||
@user.save
|
||||
end
|
||||
end
|
||||
|
||||
def process_avatar(io)
|
||||
processed = ImageProcessing::Vips
|
||||
.source(io)
|
||||
.resize_to_fill(400, 400)
|
||||
.saver(strip: true)
|
||||
.call
|
||||
io.rewind
|
||||
processed.read
|
||||
rescue Vips::Error => e
|
||||
Sentry.capture_exception(e) if Setting.sentry_enabled?
|
||||
Rails.logger.error { "Image processing failed for avatar: #{e.message}" }
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user