diff --git a/app/models/user.rb b/app/models/user.rb index 1886b1f..d15cbb0 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -159,6 +159,25 @@ class User < ApplicationRecord @display_name ||= ldap_entry[:display_name] end + def avatar + @avatar ||= LdapManager::FetchAvatar.call(cn: cn) + end + + def avatar_base64 + @avatar_base64 ||= begin + if avatar.present? + Rails.logger.debug { "Avatar data size: #{avatar.size}" } + Base64.strict_encode64(avatar) + else + Rails.logger.error { "Avatar data is empty or nil" } + return nil + end + rescue StandardError => e + Rails.logger.error { "Failed to encode avatar: #{e.message}" } + nil + end + end + def nostr_pubkey @nostr_pubkey ||= ldap_entry[:nostr_key] end @@ -186,10 +205,6 @@ class User < ApplicationRecord ZBase32.encode(Digest::SHA1.digest(cn)) end - def avatar - @avatar_base64 ||= LdapManager::FetchAvatar.call(cn: cn) - end - def services_enabled ldap_entry[:services_enabled] || [] end diff --git a/app/services/ldap_manager/fetch_avatar.rb b/app/services/ldap_manager/fetch_avatar.rb index 11035ae..be103df 100644 --- a/app/services/ldap_manager/fetch_avatar.rb +++ b/app/services/ldap_manager/fetch_avatar.rb @@ -10,7 +10,33 @@ module LdapManager filter = Net::LDAP::Filter.eq("cn", @cn) entry = client.search(base: treebase, filter: filter, attributes: attributes).first - entry.try(:jpegPhoto) ? entry.jpegPhoto.first : nil + + if entry&.jpegPhoto + binary_data = entry.jpegPhoto.first # Use first value (binary) + Rails.logger.debug { "Fetched jpegPhoto size: #{binary_data.bytesize}" } + create_tempfile(binary_data) + else + Rails.logger.debug { "No jpegPhoto found for cn=#{@cn}, ou=#{@ou}" } + nil + end + end + + def create_tempfile(binary_data) + tempfile = Tempfile.new(['image', '.jpg']) + tempfile.binmode + tempfile.write(binary_data) + tempfile.rewind + + Rails.logger.debug { "Storing debug file for cn=#{@cn}, size=#{tempfile.size}" } + + data = tempfile.read + + debug_file_path = "#{Rails.root}/tmp/avatar-fetched.jpg" + debug_file = File.open(debug_file_path, 'wb') + debug_file.write(data) + debug_file.close + + data end end end diff --git a/app/services/ldap_manager/update_avatar.rb b/app/services/ldap_manager/update_avatar.rb index f3c8975..713211a 100644 --- a/app/services/ldap_manager/update_avatar.rb +++ b/app/services/ldap_manager/update_avatar.rb @@ -8,20 +8,30 @@ module LdapManager end def call - replace_attribute @dn, :jpegPhoto, @img_data + Rails.logger.debug { "Storing jpegPhoto for dn=#{@dn}, size=#{@img_data.bytesize}" } + result = replace_attribute @dn, :jpegPhoto, @img_data + Rails.logger.debug { "LDAP replace_attribute result: #{result}" } + result end private def process(file) processed = ImageProcessing::Vips - .resize_to_fill(512, 512) + .resize_to_fill(256, 256) .source(file) .convert("jpeg") .saver(strip: true) .call - Base64.strict_encode64 processed.read + data = processed.read + + debug_file_path = "#{Rails.root}/tmp/avatar-processed.jpg" + debug_file = File.open(debug_file_path, 'wb') + debug_file.write(data) + debug_file.close + + data end end end diff --git a/app/views/settings/_profile.html.erb b/app/views/settings/_profile.html.erb index 4443e25..45ffc37 100644 --- a/app/views/settings/_profile.html.erb +++ b/app/views/settings/_profile.html.erb @@ -20,7 +20,7 @@

- Your user address for Chat and Lightning Network. + Your account's address on the Internet

<%= form_for(@user, url: setting_path(:profile), html: { :method => :put }) do |f| %> @@ -40,9 +40,10 @@ Default profile picture

- <% if current_user.avatar.present? %> + <% unless current_user.avatar.nil? %>

- <%= image_tag "data:image/jpeg;base64,#{current_user.avatar}", class: "h-24 w-24 rounded-lg" %> + <%= image_tag "data:image/jpeg;base64,#{current_user.avatar_base64}", + class: "h-24 w-24 rounded-lg" %>

<% end %>
diff --git a/spec/features/settings/profile_spec.rb b/spec/features/settings/profile_spec.rb index 55b861e..748213e 100644 --- a/spec/features/settings/profile_spec.rb +++ b/spec/features/settings/profile_spec.rb @@ -2,18 +2,22 @@ require 'rails_helper' RSpec.describe 'Profile settings', type: :feature do let(:user) { create :user, cn: "mwahlberg" } - let(:avatar_base64) { File.read("#{Rails.root}/spec/fixtures/files/avatar-base64.txt") } + let(:avatar_jpeg) { File.binread("#{Rails.root}/spec/fixtures/files/taipei.jpg") } before do + Flipper.enable "avatar_upload" + login_as user, :scope => :user allow(user).to receive(:display_name).and_return("Mark") - allow_any_instance_of(User).to receive(:dn).and_return("cn=mwahlberg,ou=kosmos.org,cn=users,dc=kosmos,dc=org") - allow_any_instance_of(User).to receive(:ldap_entry).and_return({ - uid: user.cn, ou: user.ou, display_name: "Mark", pgp_key: nil - }) - allow_any_instance_of(User).to receive(:avatar).and_return(avatar_base64) - Flipper.enable "avatar_upload" + allow_any_instance_of(User).to receive(:dn) + .and_return("cn=mwahlberg,ou=kosmos.org,cn=users,dc=kosmos,dc=org") + allow_any_instance_of(User).to receive(:ldap_entry) + .and_return({ + uid: user.cn, ou: user.ou, display_name: "Mark", pgp_key: nil + }) + allow_any_instance_of(User).to receive(:avatar) + .and_return(avatar_jpeg) end feature "Update display name" do @@ -71,7 +75,7 @@ RSpec.describe 'Profile settings', type: :feature do file_path = "#{Rails.root}/spec/fixtures/files/taipei.jpg" expect_any_instance_of(LdapManager::UpdateAvatar).to receive(:replace_attribute) - .with(user.dn, :jpegPhoto, avatar_base64).and_return(true) + .with(user.dn, :jpegPhoto, avatar_jpeg).and_return(true) visit setting_path(:profile) attach_file "Avatar", file_path