Class: GitHub::Ldap::MemberSearch::Recursive

Inherits:
Base
  • Object
show all
Includes:
Filter
Defined in:
lib/github/ldap/member_search/recursive.rb

Overview

Look up group members recursively.

This results in a maximum of ‘depth` iterations/recursions to look up members of a group and its subgroups.

Constant Summary collapse

DEFAULT_MAX_DEPTH =
9
DEFAULT_ATTRS =
%w(member uniqueMember memberUid)

Constants included from Filter

Filter::ALL_GROUPS_FILTER, Filter::MEMBERSHIP_NAMES

Instance Attribute Summary collapse

Attributes inherited from Base

#ldap

Instance Method Summary collapse

Methods included from Filter

#all_members_by_uid, #group_contains_filter, #group_filter, #login_filter, #member_filter, #members_of_group, #posix_member_filter, #subgroups_of_group

Constructor Details

#initialize(ldap, options = {}) ⇒ Recursive

Public: Instantiate new search strategy.

  • ldap: GitHub::Ldap object

  • options: Hash of options

NOTE: This overrides default behavior to configure ‘depth` and `attrs`.



26
27
28
29
30
# File 'lib/github/ldap/member_search/recursive.rb', line 26

def initialize(ldap, options = {})
  super
  @depth = options[:depth] || DEFAULT_MAX_DEPTH
  @attrs = Array(options[:attrs]).concat DEFAULT_ATTRS
end

Instance Attribute Details

#attrsObject (readonly)

Internal: The attributes to search for.



18
19
20
# File 'lib/github/ldap/member_search/recursive.rb', line 18

def attrs
  @attrs
end

#depthObject (readonly)

Internal: The maximum depth to search for members.



15
16
17
# File 'lib/github/ldap/member_search/recursive.rb', line 15

def depth
  @depth
end

Instance Method Details

#perform(group) ⇒ Object

Public: Performs search for group members, including groups and members of subgroups recursively.

Returns Array of Net::LDAP::Entry objects.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/github/ldap/member_search/recursive.rb', line 36

def perform(group)
  found = Hash.new

  # find members (N queries)
  entries = member_entries(group)
  return [] if entries.empty?

  # track found entries
  entries.each do |entry|
    found[entry.dn] = entry
  end

  # descend to `depth` levels, at most
  depth.times do |n|
    # find every (new, unique) member entry
    depth_subentries = entries.each_with_object([]) do |entry, depth_entries|
      submembers = entry["member"]

      # skip any members we've already found
      submembers.reject! { |dn| found.key?(dn) }

      # find members of subgroup, including subgroups (N queries)
      subentries = member_entries(entry)
      next if subentries.empty?

      # track found subentries
      subentries.each { |entry| found[entry.dn] = entry }

      # collect all entries for this depth
      depth_entries.concat subentries
    end

    # stop if there are no more subgroups to search
    break if depth_subentries.empty?

    # go one level deeper
    entries = depth_subentries
  end

  # return all found entries
  found.values
end