ruby-activeldap-debug 0.5.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/activeldap/associations.rb +122 -0
- data/lib/activeldap/base.rb +1244 -0
- data/lib/activeldap/configuration.rb +25 -0
- data/lib/activeldap/schema2.rb +210 -0
- data/lib/activeldap.rb +916 -0
- metadata +54 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
module ActiveLDAP
|
3
|
+
# Configuration
|
4
|
+
#
|
5
|
+
# Configuration provides the default settings required for
|
6
|
+
# ActiveLDAP to work with your LDAP server. All of these
|
7
|
+
# settings can be passed in at initialization time.
|
8
|
+
module Configuration
|
9
|
+
@@host = "127.0.0.1"
|
10
|
+
@@port = 389
|
11
|
+
@@bind_format = "uid=%s,ou=People,dc=example,dc=com"
|
12
|
+
|
13
|
+
# Make the return value the string that is your LDAP base
|
14
|
+
def Base.base
|
15
|
+
'dc=example,dc=com'
|
16
|
+
end
|
17
|
+
|
18
|
+
# This is optionally set to the array of objectClass names
|
19
|
+
# that are minimally required for EVERY object on your LDAP server.
|
20
|
+
# If you don't want one, set this to [].
|
21
|
+
def Base.required_classes
|
22
|
+
['top']
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,210 @@
|
|
1
|
+
require 'ldap'
|
2
|
+
require 'ldap/schema'
|
3
|
+
|
4
|
+
module LDAP
|
5
|
+
class Schema2 < Schema
|
6
|
+
@@attr_cache = {}
|
7
|
+
@@class_cache = {}
|
8
|
+
|
9
|
+
# attr
|
10
|
+
#
|
11
|
+
# This is just like LDAP::Schema#attr except that it allows
|
12
|
+
# look up in any of the given keys.
|
13
|
+
# e.g.
|
14
|
+
# attr('attributeTypes', 'cn', 'DESC')
|
15
|
+
# attr('ldapSyntaxes', '1.3.6.1.4.1.1466.115.121.1.5', 'DESC')
|
16
|
+
def attr(sub, type, at)
|
17
|
+
return '' if sub.empty?
|
18
|
+
return '' if type.empty?
|
19
|
+
return '' if at.empty?
|
20
|
+
|
21
|
+
# Check already parsed options first
|
22
|
+
if @@attr_cache.has_key? sub \
|
23
|
+
and @@attr_cache[sub].has_key? type \
|
24
|
+
and @@attr_cache[sub][type].has_key? at
|
25
|
+
return @@attr_cache[sub][type][at].dup
|
26
|
+
end
|
27
|
+
|
28
|
+
# Initialize anything that is required
|
29
|
+
unless @@attr_cache.has_key? sub
|
30
|
+
@@attr_cache[sub] = {}
|
31
|
+
end
|
32
|
+
|
33
|
+
unless @@attr_cache[sub].has_key? type
|
34
|
+
@@attr_cache[sub][type] = {}
|
35
|
+
end
|
36
|
+
|
37
|
+
at = at.upcase
|
38
|
+
self[sub].each do |s|
|
39
|
+
line = ''
|
40
|
+
if type[0..0] =~ /[0-9]/
|
41
|
+
line = s if s =~ /\(\s+#{type}\s+(?:[A-Z]|\))/
|
42
|
+
else
|
43
|
+
line = s if s =~ /NAME\s+\(?.*'#{type}'.*\)?\s+(?:[A-Z]|\))/
|
44
|
+
end
|
45
|
+
|
46
|
+
# I need to check, but I think some of these matchs
|
47
|
+
# overlap. I'll need to check these when I'm less sleepy.
|
48
|
+
multi = ''
|
49
|
+
case line
|
50
|
+
when /#{at}\s+[\)A-Z]/
|
51
|
+
@@attr_cache[sub][type][at] = ['TRUE']
|
52
|
+
return ['TRUE']
|
53
|
+
when /#{at}\s+'(.+?)'/
|
54
|
+
@@attr_cache[sub][type][at] = [$1]
|
55
|
+
return [$1]
|
56
|
+
when /#{at}\s+\((.+?)\)/
|
57
|
+
multi = $1
|
58
|
+
when /#{at}\s+\(([\w\d\s\.]+)\)/
|
59
|
+
multi = $1
|
60
|
+
when /#{at}\s+([\w\d\.]+)/
|
61
|
+
@@attr_cache[sub][type][at] = [$1]
|
62
|
+
return [$1]
|
63
|
+
end
|
64
|
+
# Split up multiple matches
|
65
|
+
# if oc then it is sep'd by $
|
66
|
+
# if attr then bu spaces
|
67
|
+
if multi.match(/\$/)
|
68
|
+
@@attr_cache[sub][type][at] = multi.split("$").collect{|attr| attr.strip}
|
69
|
+
return @@attr_cache[sub][type][at].dup
|
70
|
+
elsif not multi.empty?
|
71
|
+
@@attr_cache[sub][type][at] = multi.gsub(/'/, '').split(' ').collect{|attr| attr.strip}
|
72
|
+
return @@attr_cache[sub][type][at].dup
|
73
|
+
end
|
74
|
+
end
|
75
|
+
@@attr_cache[sub][type][at] = []
|
76
|
+
return []
|
77
|
+
end
|
78
|
+
|
79
|
+
# attribute_aliases
|
80
|
+
#
|
81
|
+
# Returns all names from the LDAP schema for the
|
82
|
+
# attribute given.
|
83
|
+
def attribute_aliases(attr)
|
84
|
+
attr('attributeTypes', attr, 'NAME')
|
85
|
+
end # attribute aliases
|
86
|
+
|
87
|
+
# read_only?
|
88
|
+
#
|
89
|
+
# Returns true if an attribute is read-only
|
90
|
+
# NO-USER-MODIFICATION
|
91
|
+
def read_only?(attr)
|
92
|
+
result = attr('attributeTypes', attr, 'NO-USER-MODIFICATION')
|
93
|
+
return true if result[0] == 'TRUE'
|
94
|
+
return false
|
95
|
+
end
|
96
|
+
|
97
|
+
# single_value?
|
98
|
+
#
|
99
|
+
# Returns true if an attribute can only have one
|
100
|
+
# value defined
|
101
|
+
# SINGLE-VALUE
|
102
|
+
def single_value?(attr)
|
103
|
+
result = attr('attributeTypes', attr, 'SINGLE-VALUE')
|
104
|
+
return true if result[0] == 'TRUE'
|
105
|
+
return false
|
106
|
+
end
|
107
|
+
|
108
|
+
# binary?
|
109
|
+
#
|
110
|
+
# Returns true if the given attribute's syntax
|
111
|
+
# is X-NOT-HUMAN-READABLE or X-BINARY-TRANSFER-REQUIRED
|
112
|
+
def binary?(attr)
|
113
|
+
# Get syntax OID
|
114
|
+
syntax = attr('attributeTypes', attr, 'SYNTAX')
|
115
|
+
return false if syntax.empty?
|
116
|
+
|
117
|
+
# This seems to indicate binary
|
118
|
+
result = attr('ldapSyntaxes', syntax[0], 'X-NOT-HUMAN-READABLE')
|
119
|
+
return true if result[0] == "TRUE"
|
120
|
+
|
121
|
+
# Get if binary transfer is required (non-binary types)
|
122
|
+
# Usually these have the above tag
|
123
|
+
result = attr('ldapSyntaxes', syntax[0], 'X-BINARY-TRANSFER-REQUIRED')
|
124
|
+
return true if result[0] == "TRUE"
|
125
|
+
|
126
|
+
return false
|
127
|
+
end # binary?
|
128
|
+
|
129
|
+
# binary_required?
|
130
|
+
#
|
131
|
+
# Returns true if the value MUST be transferred in binary
|
132
|
+
def binary_required?(attr)
|
133
|
+
# Get syntax OID
|
134
|
+
syntax = attr('attributeTypes', attr, 'SYNTAX')
|
135
|
+
return false if syntax.empty?
|
136
|
+
|
137
|
+
# Get if binary transfer is required (non-binary types)
|
138
|
+
# Usually these have the above tag
|
139
|
+
result = attr('ldapSyntaxes', syntax[0], 'X-BINARY-TRANSFER-REQUIRED')
|
140
|
+
return true if result[0] == "TRUE"
|
141
|
+
|
142
|
+
return false
|
143
|
+
end # binary_required?
|
144
|
+
|
145
|
+
# class_attributes
|
146
|
+
#
|
147
|
+
# Returns an Array of all the valid attributes (but not with full aliases)
|
148
|
+
# for the given objectClass
|
149
|
+
def class_attributes(objc)
|
150
|
+
if @@class_cache.has_key? objc
|
151
|
+
return @@class_cache[objc]
|
152
|
+
end
|
153
|
+
|
154
|
+
# Setup the cache
|
155
|
+
@@class_cache[objc] = {}
|
156
|
+
|
157
|
+
# First get all the current level attributes
|
158
|
+
@@class_cache[objc] = {:must => attr('objectClasses', objc, 'MUST'),
|
159
|
+
:may => attr('objectClasses', objc, 'MAY')}
|
160
|
+
|
161
|
+
# Now add all attributes from the parent object (SUPerclasses)
|
162
|
+
# Hopefully an iterative approach will be pretty speedy
|
163
|
+
# 1. build complete list of SUPs
|
164
|
+
# 2. Add attributes from each
|
165
|
+
sups = attr('objectClasses', objc, 'SUP')
|
166
|
+
loop do
|
167
|
+
start_size = sups.size
|
168
|
+
new_sups = []
|
169
|
+
sups.each do |sup|
|
170
|
+
new_sups += attr('objectClasses', sup, 'SUP')
|
171
|
+
end
|
172
|
+
sups += new_sups
|
173
|
+
sups.uniq!
|
174
|
+
break if sups.size == start_size
|
175
|
+
end
|
176
|
+
sups.each do |sup|
|
177
|
+
@@class_cache[objc][:must] += attr('objectClasses', sup, 'MUST')
|
178
|
+
@@class_cache[objc][:may] += attr('objectClasses', sup, 'MAY')
|
179
|
+
end
|
180
|
+
|
181
|
+
# Clean out the dupes.
|
182
|
+
@@class_cache[objc][:must].uniq!
|
183
|
+
@@class_cache[objc][:may].uniq!
|
184
|
+
|
185
|
+
# Return the cached value
|
186
|
+
return @@class_cache[objc].dup
|
187
|
+
end
|
188
|
+
|
189
|
+
end # Schema2
|
190
|
+
|
191
|
+
class Conn
|
192
|
+
def schema(base = nil, attrs = nil, sec = 0, usec = 0)
|
193
|
+
attrs ||= [
|
194
|
+
'objectClasses',
|
195
|
+
'attributeTypes',
|
196
|
+
'matchingRules',
|
197
|
+
'matchingRuleUse',
|
198
|
+
'dITStructureRules',
|
199
|
+
'dITContentRules',
|
200
|
+
'nameForms',
|
201
|
+
'ldapSyntaxes',
|
202
|
+
]
|
203
|
+
base ||= root_dse(['subschemaSubentry'], sec, usec)[0]['subschemaSubentry'][0]
|
204
|
+
base ||= 'cn=schema'
|
205
|
+
ent = search2(base, LDAP_SCOPE_BASE, '(objectClass=subschema)',
|
206
|
+
attrs, false, sec, usec)
|
207
|
+
return Schema2.new(ent[0])
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end # end LDAP
|