From 7b91618ffaaa021e68e37f48e69f25231cdd4b97 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A2u=20Cao?=
Date: Wed, 24 Jan 2024 15:56:34 +0300
Subject: [PATCH] WIP JPEG avatars
---
app/models/user.rb | 23 ++++++++++++++----
app/services/ldap_manager/fetch_avatar.rb | 28 +++++++++++++++++++++-
app/services/ldap_manager/update_avatar.rb | 16 ++++++++++---
app/views/settings/_profile.html.erb | 7 +++---
spec/features/settings/profile_spec.rb | 20 +++++++++-------
5 files changed, 75 insertions(+), 19 deletions(-)
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