Mailinglist Archive: opensuse-buildservice (258 mails)

< Previous Next >
[opensuse-buildservice] [PATCH] [api]Add the support for updating user info to LDAP server(optional)
  • From: "Zhang, Vivian" <vivian.zhang@xxxxxxxxx>
  • Date: Wed, 11 Aug 2010 13:18:52 +0800
  • Message-id: <625BA99ED14B2D499DC4E29D8138F15041996D3DD4@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>
Hi,

Here is a patch to provide the support for Admin updating the user info to
LDAP server (when LDAP_MODE is set) with API user management UI. Please help to
review it.
The user can use other LDAP client tool for the data updates, while it is
good to provide the option of using the API user management UI for the
updating, which is more user friendly.

vivian.

From 29c1c937f7ae220239520fc469870545597bbf84 Mon Sep 17 00:00:00 2001
From: Vivian Zhang <vivian.zhang@xxxxxxxxx>
Date: Tue, 10 Aug 2010 23:56:43 -0400
Subject: [PATCH] [api]Add the support for updating user info to LDAP
server(optional)

---
.../app/controllers/active_rbac/user_controller.rb | 39 ++++++
src/api/config/environments/production.rb | 13 ++
src/api/lib/active_rbac_mixins/user_mixins.rb | 122 ++++++++++++++++++++
3 files changed, 174 insertions(+), 0 deletions(-)

diff --git a/src/api/app/controllers/active_rbac/user_controller.rb
b/src/api/app/controllers/active_rbac/user_controller.rb
index 49f84c5..be1683b 100644
--- a/src/api/app/controllers/active_rbac/user_controller.rb
+++ b/src/api/app/controllers/active_rbac/user_controller.rb
@@ -75,6 +75,17 @@ class ActiveRbac::UserController <
ActiveRbac::ComponentController
params[:user][:groups] = [] if params[:user][:groups].nil?
@user.groups = params[:user][:groups].collect { |i| Group.find(i) }

+ # Create the new user to LDAP server if LDAP_UPDATE_SUPPORT is enabled
+ if defined?( LDAP_MODE ) && LDAP_MODE == :on
+ if defined?( LDAP_UPDATE_SUPPORT ) && LDAP_UPDATE_SUPPORT == :on
+ result = User.new_entry_ldap(params[:user][:login],
params[:user][:password],params[:user][:email])
+ if result
+ flash[:error] = result
+ return
+ end
+ end
+ end
+
# the above should be successful if we reach here; otherwise we
# have an exception and reach the rescue block below
flash[:notice] = 'User was created successfully.'
@@ -144,8 +155,23 @@ class ActiveRbac::UserController <
ActiveRbac::ComponentController
redir_to_opts[:onlyunconfirmed] = 1
end

+ # Record the old login name, which might be changed by the user
+ login = @user.login
+
# Bulk-Assign the other attributes from the form.
if @user.update_attributes(params[:user])
+ # Sync the new user data to LDAP server, if LDAP_UPDATE_SUPPORT is
enabled
+ if defined?( LDAP_MODE ) && LDAP_MODE == :on
+ if defined?( LDAP_UPDATE_SUPPORT ) && LDAP_UPDATE_SUPPORT == :on
+ result = User.update_entry_ldap(login, params[:user][:login],
params[:user][:email], params[:user][:password])
+ if result
+ flash[:error] = result
+ redirect_to :action => 'edit'
+ return
+ end
+ end
+ end
+
flash[:notice] = 'User was successfully updated.'
redirect_to redir_to_opts
else
@@ -172,7 +198,20 @@ class ActiveRbac::UserController <
ActiveRbac::ComponentController
# redirects to the #show action with the selected's user's ID.
def destroy
if not params[:yes].nil?
+ login = User.find(params[:id]).login
User.find(params[:id]).destroy
+ #Delete the user in LDAP server, if LDAP_UPDATE_SUPPORT is enabled
+ if defined?( LDAP_MODE ) && LDAP_MODE == :on
+ if defined?( LDAP_UPDATE_SUPPORT ) && LDAP_UPDATE_SUPPORT == :on
+ result = User.delete_entry_ldap(login)
+ if result
+ flash[:error] = result
+ redirect_to :action => 'list'
+ return
+ end
+ end
+ end
+
flash[:notice] = 'The user has been deleted successfully'
redirect_to :action => 'list'
else
diff --git a/src/api/config/environments/production.rb
b/src/api/config/environments/production.rb
index 7d72469..27f9ce8 100644
--- a/src/api/config/environments/production.rb
+++ b/src/api/config/environments/production.rb
@@ -58,6 +58,19 @@ LDAP_AUTHENTICATE=:ldap
LDAP_AUTH_ATTR="userPassword"
LDAP_AUTH_MECH=:md5

+# Whether to update the user info to LDAP server, it does not take effect
+# when LDAP_MODE is not set.
+# Since adding new entry operation are more depend on your slapd db define, it
might not
+# compatiable with all LDAP server settings, you can use other LDAP client
tools for your specific usage
+LDAP_UPDATE_SUPPORT = :off
+# ObjectClass, used for adding new entry
+LDAP_OBJECT_CLASS = ['inetOrgPerson']
+# Base dn for the new added entry
+LDAP_ENTRY_BASE = "ou=OBSUSERS,dc=EXAMPLE,dc=COM"
+# Does sn attribute required, it is a necessary attribute for most of people
objectclass,
+# used for adding new entry
+LDAP_SN_ATTR_REQUIRED = :on
+
SOURCE_HOST = "localhost"
SOURCE_PORT = 5352

diff --git a/src/api/lib/active_rbac_mixins/user_mixins.rb
b/src/api/lib/active_rbac_mixins/user_mixins.rb
index 6f5462a..ce72871 100644
--- a/src/api/lib/active_rbac_mixins/user_mixins.rb
+++ b/src/api/lib/active_rbac_mixins/user_mixins.rb
@@ -317,6 +317,128 @@ module UserMixins
return nil
end

+ # This static method tries to update the entry with the given info
in the
+ # active directory server. Return the error msg if any error occured
+ def self.update_entry_ldap(login, newlogin, newemail, newpassword)
+ logger.debug( " Modifying #{login} to #{newlogin} #{newemail}
using ldap" )
+
+ ldap_con = initialize_ldap_con(LDAP_SEARCH_USER, LDAP_SEARCH_AUTH)
+ if ldap_con.nil?
+ logger.debug( "Unable to connect to LDAP server" )
+ return "Unable to connect to LDAP server"
+ end
+ user_filter = "(#{LDAP_SEARCH_ATTR}=#{login})"
+ dn = String.new
+ ldap_con.search( LDAP_SEARCH_BASE, LDAP::LDAP_SCOPE_SUBTREE,
user_filter ) do |entry|
+ dn = entry.dn
+ end
+ if dn.empty?
+ logger.debug( "User not found in ldap" )
+ return "User not found in ldap"
+ end
+
+ # Update mail/password info
+ entry = [
+ LDAP.mod(LDAP::LDAP_MOD_REPLACE,LDAP_MAIL_ATTR,[newemail]),
+ ]
+ if newpassword
+ case LDAP_AUTH_MECH
+ when :cleartext then
+ entry <<
LDAP.mod(LDAP::LDAP_MOD_REPLACE,LDAP_AUTH_ATTR,[newpassword])
+ when :md5 then
+ require 'digest/md5'
+ require 'base64'
+ entry <<
LDAP.mod(LDAP::LDAP_MOD_REPLACE,LDAP_AUTH_ATTR,["{MD5}"+Base64.b64encode(Digest::MD5.digest(newpassword)).chomp])
+ end
+ end
+ begin
+ ldap_con.modify(dn, entry)
+ rescue LDAP::ResultError
+ logger.debug("Error #{ldap_con.err} for #{login} mail/password
changing")
+ return "Failed to update entry for #{login}: error
#{ldap_con.err}"
+ end
+
+ # Update the dn name if it is changed
+ if not login == newlogin
+ begin
+ ldap_con.modrdn(dn,"#{LDAP_NAME_ATTR}=#{newlogin}", true)
+ rescue LDAP::ResultError
+ logger.debug("Error #{ldap_con.err} for #{login} dn name
changing")
+ return "Failed to update dn name for #{login}: error
#{ldap_con.err}"
+ end
+ end
+
+ ldap_con.unbind()
+ return
+ end
+
+ # This static method tries to add the new entry with the given
name/password/mail info in the
+ # active directory server. Return the error msg if any error occured
+ def self.new_entry_ldap(login, password, mail)
+ require 'ldap'
+ logger.debug( "Add new entry for #{login} using ldap" )
+ ldap_con = initialize_ldap_con(LDAP_SEARCH_USER, LDAP_SEARCH_AUTH)
+ if ldap_con.nil?
+ logger.debug( "Unable to connect to LDAP server" )
+ return "Unable to connect to LDAP server"
+ end
+ case LDAP_AUTH_MECH
+ when :cleartext then
+ ldap_password = password
+ when :md5 then
+ require 'digest/md5'
+ require 'base64'
+ ldap_password =
"{MD5}"+Base64.b64encode(Digest::MD5.digest(password)).chomp
+ end
+ entry = [
+ LDAP.mod(LDAP::LDAP_MOD_ADD,'objectclass',LDAP_OBJECT_CLASS),
+ LDAP.mod(LDAP::LDAP_MOD_ADD,LDAP_NAME_ATTR,[login]),
+ LDAP.mod(LDAP::LDAP_MOD_ADD,LDAP_AUTH_ATTR,[ldap_password]),
+ LDAP.mod(LDAP::LDAP_MOD_ADD,LDAP_MAIL_ATTR,[mail]),
+ ]
+ # Added required sn attr
+ if defined?( LDAP_SN_ATTR_REQUIRED ) && LDAP_SN_ATTR_REQUIRED ==
:on
+ entry << LDAP.mod(LDAP::LDAP_MOD_ADD,'sn',[login])
+ end
+
+ begin
+ ldap_con.add("#{LDAP_NAME_ATTR}=#{login},#{LDAP_ENTRY_BASE}",
entry)
+ rescue LDAP::ResultError
+ logger.debug("Error #{ldap_con.err} for #{login}")
+ return "Failed to add a new entry for #{login}: error
#{ldap_con.err}"
+ end
+ ldap_con.unbind()
+ return
+ end
+
+ # This static method tries to delete the entry with the given login
in the
+ # active directory server. Return the error msg if any error occured
+ def self.delete_entry_ldap(login)
+ logger.debug( "Deleting #{login} using ldap" )
+ ldap_con = initialize_ldap_con(LDAP_SEARCH_USER, LDAP_SEARCH_AUTH)
+ if ldap_con.nil?
+ logger.debug( "Unable to connect to LDAP server" )
+ return "Unable to connect to LDAP server"
+ end
+ user_filter = "(#{LDAP_SEARCH_ATTR}=#{login})"
+ dn = String.new
+ ldap_con.search( LDAP_SEARCH_BASE, LDAP::LDAP_SCOPE_SUBTREE,
user_filter ) do |entry|
+ dn = entry.dn
+ end
+ if dn.empty?
+ logger.debug( "User not found in ldap" )
+ return "User not found in ldap"
+ end
+ begin
+ ldap_con.delete(dn)
+ rescue LDAP::ResultError
+ logger.debug( "Failed to delete: error #{ldap_con.err} for
#{login}" )
+ return "Failed to delete the entry #{login}: error
#{ldap_con.err}"
+ end
+ ldap_con.unbind()
+ return
+ end
+
# This static method tries to update the password with the given
login in the
# active directory server. Return the error msg if any error occured
def self.change_password_ldap(login, password)
--
1.6.1

--
To unsubscribe, e-mail: opensuse-buildservice+unsubscribe@xxxxxxxxxxxx
For additional commands, e-mail: opensuse-buildservice+help@xxxxxxxxxxxx

< Previous Next >
Follow Ups