From 51a3652fc83613b92bb03356f71d0a2ebe83ac45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A2u=20Cao?= Date: Mon, 12 May 2025 16:39:53 +0400 Subject: [PATCH] Fix S3 keys/paths for user avatars Also fixes the avatars controller to work with all back-ends --- app/controllers/avatars_controller.rb | 18 +++++++++++------ app/controllers/settings_controller.rb | 27 ++++++++++++++++++++++---- app/models/user.rb | 8 -------- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/app/controllers/avatars_controller.rb b/app/controllers/avatars_controller.rb index 5afde73..c106384 100644 --- a/app/controllers/avatars_controller.rb +++ b/app/controllers/avatars_controller.rb @@ -4,17 +4,23 @@ class AvatarsController < ApplicationController http_status :not_found and return unless user.avatar.attached? sha256_hash = params[:hash] - format = params[:format].to_sym || :png - size = params[:size]&.to_sym || :large + format = params[:format]&.to_sym || :png + size = params[:size]&.to_sym || :original - unless user.avatar_filename == "#{sha256_hash}.#{format}" + unless user.avatar.filename.to_s == "#{sha256_hash}.#{format}" http_status :not_found and return end - send_file user.avatar.service.path_for(user.avatar.key), - disposition: "inline", type: "image/#{format}" + blob = if size == :original + user.avatar.blob + else + user.avatar_variant(size: size)&.blob + end + + data = blob.download + send_data data, type: "image/#{format}", disposition: "inline" else - http_status :not_found and return + http_status :not_found end end end diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb index fc3477b..d9e202f 100644 --- a/app/controllers/settings_controller.rb +++ b/app/controllers/settings_controller.rb @@ -34,10 +34,12 @@ class SettingsController < ApplicationController end if @user.avatar_new.present? - @user.avatar.attach(@user.avatar_new) - @user.avatar.blob.update(filename: @user.avatar_filename) - @user.save! - LdapManager::UpdateAvatar.call(user: @user) + if store_user_avatar + LdapManager::UpdateAvatar.call(user: @user) + else + @validation_errors = @user.errors + render :show, status: :unprocessable_entity and return + end end if @user.pgp_pubkey && (@user.pgp_pubkey != @user.ldap_entry[:pgp_key]) @@ -187,4 +189,21 @@ class SettingsController < ApplicationController salt = BCrypt::Engine.generate_salt BCrypt::Engine.hash_secret(password, salt) end + + def store_user_avatar + data = @user.avatar_new.tempfile.read + @user.avatar_new.tempfile.rewind + hash = Digest::SHA256.hexdigest(data) + ext = @user.avatar_new.content_type == "image/png" ? "png" : "jpg" + filename = "#{hash}.#{ext}" + + if filename == @user.avatar.filename.to_s + @user.errors.add(:avatar, "must be a new file/picture") + false + else + key = "users/#{@user.cn}/avatars/#{filename}" + @user.avatar.attach io: @user.avatar_new.tempfile, key: key, filename: filename + @user.save + end + end end diff --git a/app/models/user.rb b/app/models/user.rb index 2905748..502179d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -172,14 +172,6 @@ class User < ApplicationRecord Base64.strict_encode64(data) end - def avatar_filename - return nil unless avatar.attached? - data = ActiveStorage::Blob.service.download(avatar.key) - hash = Digest::SHA256.hexdigest(data) - ext = avatar.content_type == "image/png" ? "png" : "jpg" - "#{hash}.#{ext}" - end - def avatar_variant(size: :medium) dimensions = case size when :large then [400, 400]