@@ -34,72 +34,70 @@ def initialize(ldap, options = {})
34
34
#
35
35
# Returns Array of Net::LDAP::Entry objects.
36
36
def perform ( group )
37
- found = Hash . new
38
-
39
- # find members (N queries)
40
- entries = member_entries ( group )
41
- return [ ] if entries . empty?
42
-
43
- # track found entries
44
- entries . each do |entry |
45
- found [ entry . dn ] = entry
37
+ found = Hash . new
38
+ searched = [ ]
39
+ entries = [ ]
40
+
41
+ # if this is a posixGroup, return members immediately (no nesting)
42
+ uids = member_uids ( group )
43
+ return entries_by_uid ( uids ) if uids . any?
44
+
45
+ # track group
46
+ searched << group . dn
47
+ found [ group . dn ] = group
48
+
49
+ # pull out base group's member DNs
50
+ dns = member_dns ( group )
51
+
52
+ # search for base group's subgroups
53
+ filter = ALL_GROUPS_FILTER
54
+ groups = dns . each_with_object ( [ ] ) do |dn , groups |
55
+ groups . concat ldap . search ( base : dn , scope : Net ::LDAP ::SearchScope_BaseObject , attributes : attrs , filter : filter )
56
+ searched << dn
46
57
end
47
58
48
- # descend to `depth` levels, at most
49
- depth . times do |n |
50
- # find every (new, unique) member entry
51
- depth_subentries = entries . each_with_object ( [ ] ) do |entry , depth_entries |
52
- # find members of subgroup, including subgroups (N queries)
53
- subentries = member_entries ( entry , found )
54
- next if subentries . empty?
59
+ # track found groups
60
+ groups . each { |g | found [ g . dn ] = g }
55
61
56
- # track found subentries
57
- subentries . each { |entry | found [ entry . dn ] = entry }
62
+ # recursively find subgroups
63
+ unless groups . empty?
64
+ depth . times do |n |
65
+ # pull out subgroups' member DNs to search through
66
+ sub_dns = groups . each_with_object ( [ ] ) do |subgroup , sub_dns |
67
+ sub_dns . concat member_dns ( subgroup )
68
+ end
58
69
59
- # collect all entries for this depth
60
- depth_entries . concat subentries
61
- end
70
+ # give up if there's nothing else to search for
71
+ break if sub_dns . empty?
62
72
63
- # stop if there are no more subgroups to search
64
- break if depth_subentries . empty?
73
+ # filter out if already searched for
74
+ sub_dns . reject! { | dn | searched . include? ( dn ) }
65
75
66
- # go one level deeper
67
- entries = depth_subentries
68
- end
76
+ # search for subgroups
77
+ subgroups = sub_dns . each_with_object ( [ ] ) do |dn , subgroups |
78
+ subgroups . concat ldap . search ( base : dn , scope : Net ::LDAP ::SearchScope_BaseObject , attributes : attrs , filter : filter )
79
+ searched << dn
80
+ end
69
81
70
- # return all found entries
71
- found . values
72
- end
82
+ break if subgroups . empty?
73
83
74
- # Internal: Fetch member entries, including subgroups, for the given
75
- # entry.
76
- #
77
- # Returns an Array of Net::LDAP::Entry objects.
78
- def member_entries ( entry , found = { } )
79
- entries = [ ]
80
- dns = member_dns ( entry )
81
- uids = member_uids ( entry )
84
+ # track found groups
85
+ subgroups . each { |g | found [ g . dn ] = g }
82
86
83
- # skip any entries we've already found
84
- dns . reject! { |dn | found . key? ( dn ) }
85
- uids . reject! { |uid | found . any? { |entry | entry [ 'uid' ] . include? ( uid ) } }
87
+ # descend another level
88
+ groups = subgroups
89
+ end
90
+ end
86
91
87
- entries . concat entries_by_uid ( uids ) unless uids . empty?
88
- entries . concat entries_by_dn ( dns ) unless dns . empty?
92
+ # take found groups and combine groups and members into list of entries
93
+ found . values . each do |group |
94
+ entries << group
95
+ # just need member DNs as Net::LDAP::Entry objects
96
+ entries . concat member_dns ( group ) . map { |dn | Net ::LDAP ::Entry . new ( dn ) }
97
+ end
89
98
90
99
entries
91
100
end
92
- private :member_entries
93
-
94
- # Internal: Bind a list of DNs to their respective entries.
95
- #
96
- # Returns an Array of Net::LDAP::Entry objects.
97
- def entries_by_dn ( members )
98
- members . map do |dn |
99
- ldap . domain ( dn ) . bind ( attributes : attrs )
100
- end . compact
101
- end
102
- private :entries_by_dn
103
101
104
102
# Internal: Fetch entries by UID.
105
103
#
0 commit comments