diff --git a/app/models/ldap_setting.rb b/app/models/ldap_setting.rb index 7dd1b7f..61fa0d8 100644 --- a/app/models/ldap_setting.rb +++ b/app/models/ldap_setting.rb @@ -28,9 +28,9 @@ class LdapSetting # LDAP_DESCRIPTORS LDAP_ATTRIBUTES = %w( groupname member user_memberid user_groups groupid parent_group primary_group group_parentid member_group group_memberid account_flags ) CLASS_NAMES = %w( class_user class_group ) - FLAGS = %w( create_groups create_users active ) + FLAGS = %w( create_groups create_users active create_nested_groups ) COMBOS = %w( group_membership nested_groups sync_on_login dyngroups users_search_scope ) - OTHERS = %w( account_locked_test user_fields_to_sync group_fields_to_sync user_ldap_attrs group_ldap_attrs fixed_group admin_group required_group group_search_filter groupname_pattern groups_base_dn dyngroups_cache_ttl ) + OTHERS = %w( account_locked_test user_fields_to_sync group_fields_to_sync user_ldap_attrs group_ldap_attrs fixed_group admin_group required_group group_search_filter groupname_pattern groups_base_dn dyngroups_cache_ttl nested_groups_base_dn ) validates_presence_of :auth_source_ldap_id validates_presence_of :class_user, :class_group, :groupname diff --git a/app/views/ldap_settings/_ldap_settings.html.erb b/app/views/ldap_settings/_ldap_settings.html.erb index 8b33d31..5e9f00e 100644 --- a/app/views/ldap_settings/_ldap_settings.html.erb +++ b/app/views/ldap_settings/_ldap_settings.html.erb @@ -13,6 +13,7 @@

<%= f.text_field :account_locked_test, :size => 50 %>

<%= f.select :group_membership, options_for_group_membeship %>

<%= f.select :nested_groups, options_for_nested_groups %>

+

<%= f.text_field :nested_groups_base_dn, :size => 50 %>

<%=l(:label_attribute_plural)%> diff --git a/app/views/ldap_settings/_synchronization_actions.html.erb b/app/views/ldap_settings/_synchronization_actions.html.erb index 2ca022d..8830bfb 100644 --- a/app/views/ldap_settings/_synchronization_actions.html.erb +++ b/app/views/ldap_settings/_synchronization_actions.html.erb @@ -7,6 +7,7 @@

<%= f.text_field :fixed_group, :size => 15 %>

<%= f.check_box :create_users %>

<%= f.check_box :create_groups %>

+

<%= f.check_box :create_nested_groups %>

<%= f.select :dyngroups, options_for_dyngroups %> <%= f.text_field :dyngroups_cache_ttl, :required => true, :size => 5 %> <%= l(:label_minutes) %>

diff --git a/config/locales/en.yml b/config/locales/en.yml index 8d07d04..3617b43 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -35,12 +35,14 @@ en: field_nested_groups: "Nested groups" field_create_groups: "Create groups" + field_create_nested_groups: "Create nested groups" field_create_users: "Create users" field_sync_on_login: "Synchronize on login" field_dyngroups: "Dynamic groups" field_dyngroups_cache_ttl: "Cache TTL" field_groups_base_dn: "Groups base DN" + field_nested_groups_base_dn: "Nested groups base DN" field_group_membership: "Group membership" field_class_user: "Users objectclass" field_users_search_scope: "Users search scope" diff --git a/lib/ldap_sync/entity_manager.rb b/lib/ldap_sync/entity_manager.rb index 040dfc5..881b54c 100644 --- a/lib/ldap_sync/entity_manager.rb +++ b/lib/ldap_sync/entity_manager.rb @@ -165,7 +165,8 @@ def groups_changes(user) user_dn = entry[:dn].first names_filter = groups.map{|g| Net::LDAP::Filter.eq( setting.groupid, g )}.reduce(:|) - find_all_groups(ldap, names_filter, n(:groupname)) do |group| + options = setting.has_nested_groups_base_dn? ? {:base => setting.nested_groups_base_dn} : {} + find_all_groups(ldap, names_filter, n(:groupname), options) do |group| changes[:added] << group.first end if names_filter end @@ -214,10 +215,11 @@ def reload_dyngroups! def get_group_closure(ldap, group, closure=Set.new) groupname = group.is_a?(String) ? group : group[n(:groupname)].first + options = setting.has_nested_groups_base_dn? ? {:base => setting.nested_groups_base_dn} : {} parent_groups = parents_cache.fetch(groupname) do case setting.nested_groups when 'on_members' - group = find_group(ldap, groupname, ns(:groupname, :group_memberid, :parent_group)) if group.is_a? String + group = find_group(ldap, groupname, ns(:groupname, :group_memberid, :parent_group), options) if group.is_a? String if group[n(:parent_group)].present? groups_filter = group[n(:parent_group)].map{|g| Net::LDAP::Filter.eq( setting.group_parentid, g )}.reduce(:|) @@ -226,7 +228,7 @@ def get_group_closure(ldap, group, closure=Set.new) Array.new end else # 'on_parents' - group = find_group(ldap, groupname, ns(:groupname, :group_memberid)) if group.is_a? String + group = find_group(ldap, groupname, ns(:groupname, :group_memberid), options) if group.is_a? String member_filter = Net::LDAP::Filter.eq( setting.member_group, group[n(:group_memberid)].first ) cacheable_ber find_all_groups(ldap, member_filter, ns(:groupname, :group_memberid)).map @@ -239,15 +241,15 @@ def get_group_closure(ldap, group, closure=Set.new) end end - def find_group(ldap, group_name, attrs, &block) + def find_group(ldap, group_name, attrs, options = {}, &block) extra_filter = Net::LDAP::Filter.eq( setting.groupname, group_name ) - result = find_all_groups(ldap, extra_filter, attrs, &block) + result = find_all_groups(ldap, extra_filter, attrs, options, &block) result.first if !block_given? && result.present? end def find_all_groups(ldap, extra_filter, attrs, options = {}, &block) object_class = options[:class] || setting.class_group - groups_base_dn = setting.has_groups_base_dn? ? setting.groups_base_dn : nil + groups_base_dn = options[:base] || (setting.has_groups_base_dn? ? setting.groups_base_dn : nil) group_filter = Net::LDAP::Filter.eq( :objectclass, object_class ) group_filter &= Net::LDAP::Filter.construct( setting.group_search_filter ) if setting.group_search_filter.present? group_filter &= extra_filter if extra_filter diff --git a/lib/ldap_sync/infectors/auth_source_ldap.rb b/lib/ldap_sync/infectors/auth_source_ldap.rb index a4d1103..78595d6 100644 --- a/lib/ldap_sync/infectors/auth_source_ldap.rb +++ b/lib/ldap_sync/infectors/auth_source_ldap.rb @@ -164,7 +164,13 @@ def sync_user_groups(user) end changes = groups_changes(user) - added = changes[:added].map {|g| find_or_create_group(g).first }.compact + added = changes[:added].map {|g| + if setting.create_nested_groups? + find_or_create_group(g).first + else + ::Group.where("LOWER(lastname) = ?", g.mb_chars.downcase).first + end + }.compact user.groups << added unless added.empty? deleted_groups = changes[:deleted].map {|g| g.mb_chars.downcase }