From f74227fedbf44beb4636f24012508348d9d4eb37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A2u=20Cao?=
Date: Sat, 27 May 2023 19:59:49 +0200
Subject: [PATCH] Allow users to set/update their display name in LDAP
---
app/controllers/settings_controller.rb | 60 +++++++++++--------
app/models/user.rb | 15 ++++-
.../ldap_manager/update_display_name.rb | 12 ++++
app/services/ldap_manager/update_email.rb | 2 +-
app/services/ldap_service.rb | 3 +-
app/views/settings/_account.html.erb | 2 +-
app/views/settings/_profile.html.erb | 17 ++++--
app/views/shared/_sidenav_settings.html.erb | 8 +--
config/routes.rb | 1 +
9 files changed, 79 insertions(+), 41 deletions(-)
create mode 100644 app/services/ldap_manager/update_display_name.rb
diff --git a/app/controllers/settings_controller.rb b/app/controllers/settings_controller.rb
index 01f56cd..622b623 100644
--- a/app/controllers/settings_controller.rb
+++ b/app/controllers/settings_controller.rb
@@ -12,12 +12,21 @@ class SettingsController < ApplicationController
end
def update
- @user.preferences.merge! user_params[:preferences]
- @user.save!
+ @user.preferences.merge!(user_params[:preferences] || {})
+ @user.display_name = user_params[:display_name]
- redirect_to setting_path(@settings_section), flash: {
- success: 'Settings saved.'
- }
+ if @user.save
+ if @user.display_name && (@user.display_name != @user.ldap_entry[:display_name])
+ LdapManager::UpdateDisplayName.call(@user.dn, user_params[:display_name])
+ end
+
+ redirect_to setting_path(@settings_section), flash: {
+ success: 'Settings saved.'
+ }
+ else
+ @validation_errors = @user.errors
+ render :show, status: :unprocessable_entity
+ end
end
def update_email
@@ -46,30 +55,31 @@ class SettingsController < ApplicationController
private
- def set_main_nav_section
- @current_section = :settings
- end
-
- def set_settings_section
- @settings_section = params[:section]
- allowed_sections = [:profile, :account, :lightning, :xmpp]
-
- unless allowed_sections.include?(@settings_section.to_sym)
- redirect_to setting_path(:profile)
+ def set_main_nav_section
+ @current_section = :settings
+ end
+
+ def set_settings_section
+ @settings_section = params[:section]
+ allowed_sections = [:profile, :account, :lightning, :xmpp]
+
+ unless allowed_sections.include?(@settings_section.to_sym)
+ redirect_to setting_path(:profile)
+ end
end
- end
- def user_params
- params.require(:user).permit(preferences: [
- :lightning_notify_sats_received,
- :xmpp_exchange_contacts_with_invitees
- ])
- end
def set_user
@user = current_user
end
- def email_params
- params.require(:user).permit(:email, :current_password)
- end
+ def user_params
+ params.require(:user).permit(:display_name, preferences: [
+ :lightning_notify_sats_received,
+ :xmpp_exchange_contacts_with_invitees
+ ])
+ end
+
+ def email_params
+ params.require(:user).permit(:email, :current_password)
+ end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 93b7a5d..07d1bbe 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,6 +1,8 @@
class User < ApplicationRecord
include EmailValidatable
+ attr_accessor :display_name
+
serialize :preferences, UserPreferences
# Relations
@@ -17,7 +19,7 @@ class User < ApplicationRecord
has_many :accounts, through: :lndhub_user
validates_uniqueness_of :cn
- validates_length_of :cn, :minimum => 3
+ validates_length_of :cn, minimum: 3
validates_format_of :cn, with: /\A([a-z0-9\-])*\z/,
if: Proc.new{ |u| u.cn.present? },
message: "is invalid. Please use only letters, numbers and -"
@@ -31,6 +33,8 @@ class User < ApplicationRecord
validates_uniqueness_of :email
validates :email, email: true
+ validates_length_of :display_name, minimum: 3, maximum: 35, allow_blank: true
+
scope :confirmed, -> { where.not(confirmed_at: nil) }
scope :pending, -> { where(confirmed_at: nil) }
@@ -115,8 +119,13 @@ class User < ApplicationRecord
@dn = Devise::LDAP::Adapter.get_dn(self.cn)
end
- def ldap_entry
- ldap.fetch_users(uid: self.cn, ou: self.ou).first
+ def ldap_entry(reload: false)
+ return @ldap_entry if defined?(@ldap_entry) && !reload
+ @ldap_entry = ldap.fetch_users(uid: self.cn, ou: self.ou).first
+ end
+
+ def display_name
+ @display_name ||= ldap_entry[:display_name]
end
def services_enabled
diff --git a/app/services/ldap_manager/update_display_name.rb b/app/services/ldap_manager/update_display_name.rb
new file mode 100644
index 0000000..2d3e90f
--- /dev/null
+++ b/app/services/ldap_manager/update_display_name.rb
@@ -0,0 +1,12 @@
+module LdapManager
+ class UpdateDisplayName < LdapManagerService
+ def initialize(dn, display_name)
+ @dn = dn
+ @display_name = display_name
+ end
+
+ def call
+ replace_attribute @dn, :displayName, @display_name
+ end
+ end
+end
diff --git a/app/services/ldap_manager/update_email.rb b/app/services/ldap_manager/update_email.rb
index 5acd77f..80f40e4 100644
--- a/app/services/ldap_manager/update_email.rb
+++ b/app/services/ldap_manager/update_email.rb
@@ -6,7 +6,7 @@ module LdapManager
end
def call
- replace_attribute @dn, :mail, [ @address ]
+ replace_attribute @dn, :mail, @address
end
end
end
diff --git a/app/services/ldap_service.rb b/app/services/ldap_service.rb
index 5a572c5..eac64c2 100644
--- a/app/services/ldap_service.rb
+++ b/app/services/ldap_service.rb
@@ -50,7 +50,7 @@ class LdapService < ApplicationService
treebase = ldap_config["base"]
end
- attributes = %w{dn cn uid mail admin service}
+ attributes = %w{dn cn uid mail displayName admin service}
filter = Net::LDAP::Filter.eq("uid", args[:uid] || "*")
entries = ldap_client.search(base: treebase, filter: filter, attributes: attributes)
@@ -59,6 +59,7 @@ class LdapService < ApplicationService
{
uid: e.uid.first,
mail: e.try(:mail) ? e.mail.first : nil,
+ display_name: e.try(:displayName) ? e.displayName.first : nil,
admin: e.try(:admin) ? 'admin' : nil,
service: e.try(:service)
}
diff --git a/app/views/settings/_account.html.erb b/app/views/settings/_account.html.erb
index cba8715..5726230 100644
--- a/app/views/settings/_account.html.erb
+++ b/app/views/settings/_account.html.erb
@@ -34,7 +34,7 @@
<%= f.password_field :current_password, class: "w-full", required: true %>
- <%= f.submit "Update", class: "btn-md btn-blue" %>
+ <%= f.submit "Update", class: "btn-md btn-blue w-full md:w-auto" %>
<% end %>
diff --git a/app/views/settings/_profile.html.erb b/app/views/settings/_profile.html.erb
index f1d14ae..e72430c 100644
--- a/app/views/settings/_profile.html.erb
+++ b/app/views/settings/_profile.html.erb
@@ -21,10 +21,15 @@
Your user address for Chat and Lightning Network.
-
- <%# <%= form_for(@user, as: "profile", url: settings_profile_path) do |f| %>
- <%#
- <%# <%= f.submit "Save changes", class: 'btn-md btn-blue w-full sm:w-auto' %>
- <%#
- <%# <% end %>
+ <%= form_for(@user, url: setting_path(:profile), html: { :method => :put }) do |f| %>
+ <%= render FormElements::FieldsetComponent.new(tag: "div", title: "Display name") do %>
+ <%= f.text_field :display_name, class: "w-full sm:w-3/5 mb-2" %>
+ <% if @validation_errors.present? && @validation_errors[:display_name].present? %>
+ <%= @validation_errors[:display_name].first %>
+ <% end %>
+ <% end %>
+
+ <%= f.submit 'Save', class: "btn-md btn-blue w-full md:w-auto" %>
+
+ <% end %>
diff --git a/app/views/shared/_sidenav_settings.html.erb b/app/views/shared/_sidenav_settings.html.erb
index 3ebf8e1..ce2a527 100644
--- a/app/views/shared/_sidenav_settings.html.erb
+++ b/app/views/shared/_sidenav_settings.html.erb
@@ -1,20 +1,20 @@
<%= render SidenavLinkComponent.new(
name: "Profile", path: setting_path(:profile), icon: "user",
- active: current_page?(setting_path(:profile))
+ active: @settings_section.to_s == "profile"
) %>
<%= render SidenavLinkComponent.new(
name: "Account", path: setting_path(:account), icon: "key",
- active: current_page?(setting_path(:account))
+ active: @settings_section.to_s == "account"
) %>
<% if Setting.ejabberd_enabled %>
<%= render SidenavLinkComponent.new(
name: "Chat", path: setting_path(:xmpp), icon: "message-circle",
- active: current_page?(setting_path(:xmpp))
+ active: @settings_section.to_s == "xmpp"
) %>
<% end %>
<% if Setting.lndhub_enabled %>
<%= render SidenavLinkComponent.new(
name: "Lightning", path: setting_path(:lightning), icon: "zap",
- active: current_page?(setting_path(:lightning))
+ active: @settings_section.to_s == "lightning"
) %>
<% end %>
diff --git a/config/routes.rb b/config/routes.rb
index a369bd3..71f7620 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -28,6 +28,7 @@ Rails.application.routes.draw do
resources :settings, param: 'section', only: ['index', 'show', 'update'] do
collection do
+ post 'update_profile'
post 'update_email'
post 'reset_password'
end