3 Commits

Author SHA1 Message Date
Râu Cao
d5ab532947 Store and retrieve avatars in/from LDAP exclusively
Some checks failed
continuous-integration/drone/push Build is failing
No need to keep them in two places at the same time. We can fetch them
from LDAP whenever we want to do something with them.
2023-09-06 20:42:26 +02:00
Râu Cao
50c63d5c38 Update user avatar in LDAP 2023-09-06 19:02:07 +02:00
Râu Cao
64d09cfb7f Use variant declarations instead of custom methods 2023-09-06 12:38:47 +02:00
8 changed files with 68 additions and 19 deletions

View File

@@ -20,6 +20,8 @@ class Admin::UsersController < Admin::BaseController
end
@services_enabled = @user.services_enabled
@avatar = LdapManager::FetchAvatar.call(cn: @user.cn, ou: @user.ou)
end
private

View File

@@ -19,11 +19,15 @@ class SettingsController < ApplicationController
def update
@user.preferences.merge!(user_params[:preferences] || {})
@user.display_name = user_params[:display_name]
@user.avatar = user_params[:avatar] if user_params[:avatar].present?
@user.avatar_new = user_params[:avatar]
if @user.save
if @user.display_name && (@user.display_name != @user.ldap_entry[:display_name])
LdapManager::UpdateDisplayName.call(@user.dn, user_params[:display_name])
LdapManager::UpdateDisplayName.call(@user.dn, @user.display_name)
end
if @user.avatar_new.present?
LdapManager::UpdateAvatar.call(@user.dn, @user.avatar_new)
end
redirect_to setting_path(@settings_section), flash: {

View File

@@ -2,15 +2,10 @@ class User < ApplicationRecord
include EmailValidatable
attr_accessor :display_name
attr_accessor :avatar_new
serialize :preferences, UserPreferences
#
# File attachments
#
has_one_attached :avatar
#
# Relations
#
@@ -163,12 +158,8 @@ class User < ApplicationRecord
@display_name ||= ldap_entry[:display_name]
end
def avatar_64px
avatar.variant(resize_to_fill: [64, 64])
end
def avatar_256px
avatar.variant(resize_to_fill: [256, 256])
def avatar
@avatar_base64 ||= LdapManager::FetchAvatar.call(cn: cn, ou: ou)
end
def services_enabled
@@ -201,14 +192,14 @@ class User < ApplicationRecord
end
def acceptable_avatar
return unless avatar.attached?
return unless avatar_new.present?
if avatar.blob.byte_size > 1.megabyte
if avatar_new.size > 1.megabyte
errors.add(:avatar, "file size is too large")
end
acceptable_types = ["image/jpeg", "image/png"]
unless acceptable_types.include?(avatar.content_type)
unless acceptable_types.include?(avatar_new.content_type)
errors.add(:avatar, "must be a JPEG or PNG file")
end
end

View File

@@ -0,0 +1,18 @@
module LdapManager
class FetchAvatar < LdapManagerService
def initialize(cn:, ou: nil)
@cn = cn
@ou = ou
end
def call
treebase = @ou ? "ou=#{@ou},cn=users,#{suffix}" : ldap_config["base"]
puts treebase.inspect
attributes = %w{ jpegPhoto }
filter = Net::LDAP::Filter.eq("cn", @cn)
entry = ldap_client.search(base: treebase, filter: filter, attributes: attributes).first
entry.try(:jpegPhoto) ? entry.jpegPhoto.first : nil
end
end
end

View File

@@ -0,0 +1,27 @@
require "image_processing/vips"
module LdapManager
class UpdateAvatar < LdapManagerService
def initialize(dn, file)
@dn = dn
@img_data = process(file)
end
def call
replace_attribute @dn, :jpegPhoto, @img_data
end
private
def process(file)
processed = ImageProcessing::Vips
.resize_to_fill(512, 512)
.source(file)
.convert("jpeg")
.saver(strip: true)
.call
Base64.strict_encode64 processed.read
end
end
end

View File

@@ -1,2 +1,5 @@
class LdapManagerService < LdapService
def suffix
@suffix ||= ENV["LDAP_SUFFIX"] || "dc=kosmos,dc=org"
end
end

View File

@@ -63,6 +63,10 @@
</section>
<section class="sm:flex-1 sm:pt-0">
<h3>LDAP<h3>
<p>
<img src="data:image/png;base64,<%= @avatar %>" class="h-48 w-48" />
</p>
<!-- <h3>Actions</h3> -->
</section>
</div>

View File

@@ -39,9 +39,9 @@
Default profile picture
</p>
<div class="flex items-center gap-6">
<% if current_user.avatar.attached? %>
<% if current_user.avatar.present? %>
<p class="flex-none">
<%= image_tag current_user.reload.avatar_256px, class: "h-24 w-24 rounded-lg" %>
<%= image_tag "data:image/jpeg;base64,#{current_user.avatar}", class: "h-24 w-24 rounded-lg" %>
</p>
<% end %>
<div class="grow">