ucb_ldap 2.0.0.pre1 → 2.0.0.pre3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/CHANGELOG +137 -135
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/{README → README.md} +82 -80
  7. data/Rakefile +38 -20
  8. data/lib/ucb_ldap.rb +238 -204
  9. data/lib/{ucb_ldap_address.rb → ucb_ldap/address.rb} +106 -106
  10. data/lib/{ucb_ldap_affiliation.rb → ucb_ldap/affiliation.rb} +16 -16
  11. data/lib/{ucb_ldap_entry.rb → ucb_ldap/entry.rb} +455 -448
  12. data/lib/{ucb_ldap_person_job_appointment.rb → ucb_ldap/job_appointment.rb} +77 -79
  13. data/lib/{ucb_ldap_namespace.rb → ucb_ldap/namespace.rb} +40 -50
  14. data/lib/{ucb_ldap_org.rb → ucb_ldap/org.rb} +427 -429
  15. data/lib/{ucb_ldap_person.rb → ucb_ldap/person.rb} +157 -148
  16. data/lib/{person → ucb_ldap/person}/affiliation_methods.rb +23 -22
  17. data/lib/ucb_ldap/person/common_attributes.rb +63 -0
  18. data/lib/{ucb_ldap_schema.rb → ucb_ldap/schema.rb} +28 -28
  19. data/lib/{ucb_ldap_schema_attribute.rb → ucb_ldap/schema_attribute.rb} +152 -153
  20. data/lib/{ucb_ldap_service.rb → ucb_ldap/service.rb} +17 -19
  21. data/lib/{ucb_ldap_student_term.rb → ucb_ldap/student_term.rb} +29 -31
  22. data/lib/ucb_ldap/version.rb +3 -0
  23. data/spec/rails_binds.yml +9 -0
  24. data/spec/spec_helper.rb +43 -0
  25. data/spec/ucb_ldap/address_spec.rb +54 -0
  26. data/spec/ucb_ldap/affiliation_spec.rb +85 -0
  27. data/spec/ucb_ldap/entry_spec.rb +241 -0
  28. data/spec/ucb_ldap/job_appointment_spec.rb +65 -0
  29. data/spec/ucb_ldap/namespace_spec.rb +72 -0
  30. data/spec/ucb_ldap/org_spec.rb +217 -0
  31. data/spec/ucb_ldap/person_spec.rb +225 -0
  32. data/spec/ucb_ldap/schema_attribute_spec.rb +122 -0
  33. data/spec/ucb_ldap/schema_spec.rb +104 -0
  34. data/spec/ucb_ldap/service_spec.rb +127 -0
  35. data/spec/ucb_ldap/student_term_spec.rb +121 -0
  36. data/spec/ucb_ldap_spec.rb +182 -0
  37. data/ucb_ldap.gemspec +20 -27
  38. metadata +113 -64
  39. data/Manifest +0 -23
  40. data/TODO +0 -2
  41. data/lib/person/adv_con_person.rb +0 -0
  42. data/lib/person/generic_attributes.rb +0 -68
  43. data/lib/ucb_ldap_exceptions.rb +0 -27
  44. data/version.yml +0 -1
@@ -1,8 +1,7 @@
1
-
2
1
  module UCB
3
2
  module LDAP
4
3
  # = UCB::LDAP::StudentTerm
5
- #
4
+ #
6
5
  # This class models a student's term entries in the UCB LDAP directory.
7
6
  #
8
7
  # terms = StudentTerm.find_by_uid("1234") #=> [#<UCB::LDAP::StudentTerm: ...>, ...]
@@ -13,7 +12,7 @@ module UCB
13
12
  # terms = p.student_terms #=> [#<UCB::LDAP::StudentTerm: ...>, ...]
14
13
  #
15
14
  # == Note on Binds
16
- #
15
+ #
17
16
  # You must have a privileged bind and pass your credentials to UCB::LDAP.authenticate()
18
17
  # before performing your StudentTerm search.
19
18
  #
@@ -23,79 +22,78 @@ module UCB
23
22
  def change_datetime
24
23
  UCB::LDAP.local_datetime_parse(berkeleyEduStuChangeDate)
25
24
  end
26
-
25
+
27
26
  def college_code
28
27
  berkeleyEduStuCollegeCode
29
28
  end
30
-
29
+
31
30
  def college_name
32
31
  berkeleyEduStuCollegeName
33
32
  end
34
-
33
+
35
34
  def level_code
36
35
  berkeleyEduStuEduLevelCode
37
36
  end
38
-
37
+
39
38
  def level_name
40
39
  berkeleyEduStuEduLevelName
41
40
  end
42
-
41
+
43
42
  def role_code
44
43
  berkeleyEduStuEduRoleCode
45
44
  end
46
-
45
+
47
46
  def role_name
48
47
  berkeleyEduStuEduRoleName
49
48
  end
50
-
49
+
51
50
  def major_code
52
51
  berkeleyEduStuMajorCode
53
52
  end
54
-
53
+
55
54
  def major_name
56
55
  berkeleyEduStuMajorName
57
56
  end
58
-
57
+
59
58
  def registration_status_code
60
59
  berkeleyEduStuRegStatCode
61
60
  end
62
-
61
+
63
62
  def registration_status_name
64
63
  berkeleyEduStuRegStatName
65
64
  end
66
-
65
+
67
66
  def term_code
68
67
  berkeleyEduStuTermCode
69
68
  end
70
-
69
+
71
70
  def term_name
72
71
  berkeleyEduStuTermName
73
72
  end
74
-
73
+
75
74
  def term_status
76
75
  berkeleyEduStuTermStatus
77
76
  end
78
-
77
+
79
78
  def term_year
80
79
  berkeleyEduStuTermYear
81
80
  end
82
-
81
+
83
82
  def under_graduate_code
84
83
  berkeleyEduStuUGCode
85
84
  end
86
-
87
- class << self
88
- # Returns an Array of JobAppointment for <tt>uid</tt>, sorted by
89
- # record_number().
90
- # Returns an empty Array ([]) if nothing is found.
91
- #
92
- def find_by_uid(uid)
93
- base = "uid=#{uid},ou=people,dc=berkeley,dc=edu"
94
- filter = Net::LDAP::Filter.eq("objectclass", 'berkeleyEduPersonTerm')
95
- search(:base => base, :filter => filter)
96
- end
97
-
85
+
86
+ ##
87
+ # Returns an Array of JobAppointment for <tt>uid</tt>, sorted by
88
+ # record_number().
89
+ # Returns an empty Array ([]) if nothing is found.
90
+ #
91
+ def self.find_by_uid(uid)
92
+ base = "uid=#{uid},ou=people,dc=berkeley,dc=edu"
93
+ filter = Net::LDAP::Filter.eq("objectclass", 'berkeleyEduPersonTerm')
94
+ search(:base => base, :filter => filter)
98
95
  end
96
+
99
97
  end
100
98
  end
101
- end
99
+ end
@@ -0,0 +1,3 @@
1
+ module UcbLdap
2
+ VERSION = "2.0.0.pre3"
3
+ end
@@ -0,0 +1,9 @@
1
+ # Used for testing Rails binds -- these aren't real credentials
2
+ development:
3
+ username: username_development
4
+ password: password_development
5
+
6
+ production:
7
+ username: username_production
8
+ password: password_production
9
+
@@ -0,0 +1,43 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+ require_relative "../lib/ucb_ldap"
4
+
5
+ RSpec.configure do |config|
6
+ # config block
7
+ end
8
+
9
+ $TESTING = true
10
+
11
+ include UCB::LDAP
12
+ UCB::LDAP.host = "ldap-test.berkeley.edu"
13
+
14
+ $binds ||= YAML.load(IO.read("#{File.dirname(__FILE__)}/binds.yml"))
15
+
16
+ def bind_for(bind_key)
17
+ bind = $binds[bind_key] or raise("No bind found for '#{bind_key}'")
18
+ UCB::LDAP.authenticate(bind["username"], bind["password"])
19
+ end
20
+
21
+ def address_bind
22
+ bind_for("address")
23
+ end
24
+
25
+ def job_appointment_bind
26
+ bind_for("job_appointment")
27
+ end
28
+
29
+ def namespace_bind
30
+ bind_for("namespace")
31
+ end
32
+
33
+ def org_bind
34
+ bind_for("org")
35
+ end
36
+
37
+ def affiliation_bind
38
+ bind_for("affiliation")
39
+ end
40
+
41
+ def service_bind
42
+ bind_for("affiliation")
43
+ end
@@ -0,0 +1,54 @@
1
+ require_relative "../spec_helper"
2
+
3
+
4
+ describe "UCB::LDAP::Address" do
5
+ before(:all) do
6
+ address_bind
7
+ end
8
+
9
+ before(:each) do
10
+ # assumes 'sh' has 1 address, 'ba' has 1
11
+ @sh_addresses = Address.find_by_uid('61065')
12
+ @ba_addresses = Address.find_by_uid('230455')
13
+ end
14
+
15
+ after(:all) do
16
+ UCB::LDAP.clear_authentication
17
+ end
18
+
19
+ it "should find addresses by uid" do
20
+ @sh_addresses.should be_instance_of(Array)
21
+ @sh_addresses.first.should be_instance_of(Address)
22
+ @sh_addresses.size.should == 1
23
+
24
+ @ba_addresses.size.should == 1
25
+ end
26
+
27
+ it "should know primary work address" do
28
+ @sh_addresses.first.should be_primary_work_address
29
+
30
+ @ba_addresses.each do |addr|
31
+ addr.should(be_primary_work_address) if addr.berkeleyEduPersonAddressPrimaryFlag
32
+ addr.should_not(be_primary_work_address) if !addr.berkeleyEduPersonAddressPrimaryFlag
33
+ end
34
+ end
35
+
36
+ it "should return addresses in sort order" do
37
+ [@sh_addresses, @ba_addresses].each do |addresses|
38
+ addresses.each_with_index do |addr, i|
39
+ addr.sort_order.should == (i + 1)
40
+ end
41
+ end
42
+ end
43
+
44
+ # it "should print itself" do
45
+ # [@sh_addresses, @ba_addresses].flatten.each do |a|
46
+ # puts "----"
47
+ # a.attributes.keys.sort_by{|k|k.to_s}.each do |k|
48
+ # puts "#{k}: #{a.attributes[k].inspect}"#, a.send(k).inspect
49
+ # end
50
+ # end
51
+ # end
52
+
53
+ end
54
+
@@ -0,0 +1,85 @@
1
+ require_relative "../spec_helper"
2
+
3
+
4
+ describe "UCB::LDAP::Affiliation" do
5
+ before(:all) do
6
+ affiliation_bind
7
+ @uid = "61065"
8
+ @student = Person.find_by_uid(@uid)
9
+ @datetime_string = '20010203040506Z'
10
+ @datetime_expected = '2001-02-02T20:05:06-08:00'
11
+ @date_expected = '2001-02-02'
12
+ end
13
+
14
+ after(:all) do
15
+ UCB::LDAP.clear_authentication
16
+ end
17
+
18
+ it "should find affiliations by uid" do
19
+ Affiliation.find_by_uid(@uid).class.should == Array
20
+ end
21
+
22
+ it "should find affiliations from Person" do
23
+ @student.affiliations.class.should == Array
24
+ end
25
+
26
+ it "should return create_datetime" do
27
+ Affiliation.new({}).create_datetime.should be_nil
28
+ Affiliation.new(:berkeleyEduAffCreateDate => [@datetime_string]).create_datetime.to_s.should == @datetime_expected
29
+ end
30
+
31
+ it "should return expired_by" do
32
+ Affiliation.new({}).expired_by.should be_nil
33
+ Affiliation.new(:berkeleyEduAffExpBy => ['foo']).expired_by.to_s.should == 'foo'
34
+ end
35
+
36
+ it "should return expiration_date" do
37
+ Affiliation.new({}).expiration_date.should be_nil
38
+ Affiliation.new(:berkeleyEduAffExpDate => [@datetime_string]).expiration_date.to_s.should == @date_expected
39
+ end
40
+
41
+ it "should return affiliate_id" do
42
+ Affiliation.new({}).affiliate_id.should be_nil
43
+ Affiliation.new(:berkeleyEduAffID => ['foo']).affiliate_id.to_s.should == 'foo'
44
+ end
45
+
46
+ it "should return affiliate_type" do
47
+ Affiliation.new({}).affiliate_type.should be_nil
48
+ Affiliation.new(:berkeleyEduAffType => ['foo']).affiliate_type.to_s.should == 'foo'
49
+ end
50
+
51
+ it "should return first_name" do
52
+ Affiliation.new({}).first_name.should be_nil
53
+ Affiliation.new(:givenName => ['foo']).first_name.to_s.should == 'foo'
54
+ end
55
+
56
+ it "should return middle_name" do
57
+ Affiliation.new({}).middle_name.should be_nil
58
+ Affiliation.new(:berkeleyEduMiddleName => ['foo']).middle_name.to_s.should == 'foo'
59
+ end
60
+
61
+ it "should return last_name" do
62
+ Affiliation.new({}).last_name.should be_nil
63
+ Affiliation.new(:sn => ['foo']).last_name.to_s.should == 'foo'
64
+ end
65
+
66
+ it "should return modified_by" do
67
+ Affiliation.new({}).modified_by.should be_nil
68
+ Affiliation.new(:berkeleyEduModifiedBy => ['foo']).modified_by.to_s.should == 'foo'
69
+ end
70
+
71
+ it "should return source" do
72
+ Affiliation.new({}).source.should be_nil
73
+ Affiliation.new(:berkeleyEduPersonAffiliateSource => ['foo']).source.to_s.should == 'foo'
74
+ end
75
+
76
+ it "should return dept_code" do
77
+ Affiliation.new({}).dept_code.should be_nil
78
+ Affiliation.new(:departmentNumber => ['foo']).dept_code.to_s.should == 'foo'
79
+ end
80
+
81
+ it "should return dept_name" do
82
+ Affiliation.new({}).dept_name.should be_nil
83
+ Affiliation.new(:berkeleyEduUnitCalNetDeptName => ['foo']).dept_name.to_s.should == 'foo'
84
+ end
85
+ end
@@ -0,0 +1,241 @@
1
+ require_relative '../spec_helper'
2
+
3
+
4
+ describe UCB::LDAP::Entry do
5
+ before(:each) do
6
+ Entry.stub!(:entity_name).and_return("org")
7
+ Entry.schema_attributes_array # force load
8
+ end
9
+
10
+ it "should make canonical attribute names" do
11
+ Entry.canonical("firstLast").should == :firstlast
12
+ Entry.canonical("FIRSTLAST").should == :firstlast
13
+ Entry.canonical(:FIRSTLAST).should == :firstlast
14
+ end
15
+
16
+ it "should return an Array of object_classes" do
17
+ Entry.object_classes.should == %w{top organizationalunit berkeleyEduOrgUnit}
18
+ end
19
+
20
+ it "should return unique object class" do
21
+ Entry.unique_object_class.should == 'berkeleyEduOrgUnit'
22
+ end
23
+
24
+ it "should return an Array of Schema::Attribute" do
25
+ Entry.schema_attributes_array.should be_instance_of(Array)
26
+ Entry.schema_attributes_array[0].should be_instance_of(Schema::Attribute)
27
+ end
28
+
29
+ it "schema_attribute works by name, alias, symbol, any-case version of same" do
30
+ fax_attr = Entry.schema_attributes_array.find { |attr| attr.name == "facsimileTelephoneNumber" }
31
+ fax_attr.aliases.should == ["fax"]
32
+ ["facsimileTelephoneNumber", "facsimiletelephonenumber",
33
+ "fax", "FAX", :fax].each do |version|
34
+ Entry.schema_attribute(version).should equal(fax_attr)
35
+ end
36
+ end
37
+
38
+ it "should raise exception trying to access bad attribute name" do
39
+ lambda { Entry.schema_attribute("bogus") }.should raise_error(BadAttributeNameException)
40
+ end
41
+
42
+ it "should know which of its attributes are required" do
43
+ # commonname is an alias for cn
44
+ # userid is an alias for uid
45
+ # surname is an alias for sn
46
+ # aliases should not show up in the required attributes
47
+ required_person_attributes = [:cn, :objectclass, :sn, :uid]
48
+
49
+ TestPerson = Class.new(Entry)
50
+ TestPerson.stub!(:entity_name).and_return("person")
51
+ TestPerson.required_attributes.length.should == required_person_attributes.length
52
+ TestPerson.required_attributes.each do |attr|
53
+ required_person_attributes.should include(attr)
54
+ end
55
+ end
56
+ end
57
+
58
+
59
+ describe "UCB::LDAP::Entry instance" do
60
+ before(:each) do
61
+ Entry.stub!(:entity_name).and_return("org")
62
+ Entry.schema_attributes_array # force load
63
+ @e = Entry.new("facsimileTelephoneNumber" => ["1", "2"], :dn => ["dn"])
64
+ end
65
+
66
+ it "should make canonical attribute names" do
67
+ @e.canonical("firstLast").should == :firstlast
68
+ @e.canonical("FIRSTLAST").should == :firstlast
69
+ @e.canonical(:FIRSTLAST).should == :firstlast
70
+ end
71
+
72
+ it "should return dn (Distinguished Name)" do
73
+ @e.dn.should == ["dn"]
74
+ end
75
+
76
+ it "should raise NoMethodError if bad attribute name treated like method" do
77
+ lambda { @e.bogus }.should raise_error(NoMethodError)
78
+ end
79
+
80
+ it "should retrieve values by 'official' attribute name as instance method" do
81
+ @e.facsimileTelephoneNumber.should == ["1", "2"]
82
+ end
83
+
84
+ it "should retrieve values by any-cased name as instance method" do
85
+ @e.facsimiletelephonenumber.should == ["1", "2"]
86
+ end
87
+
88
+ it "should retrieve values by alias" do
89
+ @e.fax.should == ["1", "2"]
90
+ end
91
+
92
+ it "should return scalar result for scalars" do
93
+ @e = Entry.new("berkeleyEduOrgUnitProcessUnitFlag" => ["true"])
94
+ @sa = Entry.schema_attribute("berkeleyEduOrgUnitProcessUnitFlag")
95
+ @e.berkeleyEduOrgUnitProcessUnitFlag.should be_true
96
+ end
97
+
98
+ it "should return array result for multi-valued attributes" do
99
+ @e.facsimileTelephoneNumber.should == ["1", "2"]
100
+ end
101
+
102
+ it "setter methods end in '='" do
103
+ @e.send(:setter_method?, :foo=).should be_true
104
+ @e.send(:setter_method?, "foo=").should be_true
105
+ @e.send(:setter_method?, :foo).should be_false
106
+ @e.send(:setter_method?, "foo").should be_false
107
+ end
108
+ end
109
+
110
+
111
+ describe "Setting UCB::LDAP::Namespace attributes" do
112
+ before(:all) do
113
+ namespace_bind # _setup_specs.rb
114
+ end
115
+
116
+ before(:each) do
117
+ @namespace = Namespace.find_by_uid("61065").first
118
+ end
119
+
120
+ after(:all) do
121
+ UCB::LDAP.clear_authentication
122
+ end
123
+
124
+ it "should set assigned attributes when set w/scalar" do
125
+ @namespace.cn = "a_name"
126
+ @namespace.assigned_attributes[:cn].should == ["a_name"]
127
+ end
128
+
129
+ it "should set assigned attributes when set w/array" do
130
+ @namespace.cn = ["a", "b"]
131
+ @namespace.assigned_attributes[:cn].should == ["a", "b"]
132
+ end
133
+
134
+ it "should set assigned attributes when set w/nil" do
135
+ @namespace.cn = nil
136
+ @namespace.assigned_attributes[:cn].should be_nil
137
+ end
138
+
139
+ it "should trim leading/trailing spaces and imbedded newlines" do
140
+ @namespace.cn = " foo\nbar "
141
+ @namespace.assigned_attributes[:cn].should == ['foobar']
142
+ end
143
+
144
+ it "should set modify operations correctly" do
145
+ @namespace.cn = ["CN"]
146
+ @namespace.uid = nil
147
+ @namespace.berkeleyEduServices = ["s1", "s2"]
148
+ @namespace.modify_operations.should == [
149
+ [:replace, :berkeleyeduservices, ["s1", "s2"]],
150
+ [:replace, :cn, ["CN"]],
151
+ [:delete, :uid, nil]
152
+ ]
153
+ end
154
+ end
155
+
156
+
157
+ describe "Updating UCB::LDAP::Namespace entries" do
158
+ before(:all) do
159
+ UCB::LDAP.host == HOST_TEST
160
+ namespace_bind
161
+ end
162
+
163
+ before(:each) do
164
+ @uid = '61065'
165
+ @cn = 'test_add'
166
+ @dn_base = 'ou=names,ou=namespace,dc=berkeley,dc=edu'
167
+ delete_by_cn(@cn)
168
+ end
169
+
170
+ after(:all) do
171
+ UCB::LDAP.clear_authentication
172
+ end
173
+
174
+ def delete_by_cn(cn)
175
+ Namespace.find_by_cn(cn).delete rescue nil
176
+ end
177
+
178
+ def add_entry(cn, services="calnet", method="create")
179
+ dn = "cn=#{cn},#{@dn_base}"
180
+ attrs = { :cn => @cn, :berkeleyEduServices => services, :uid => @uid }
181
+ Namespace.send(method, :dn => dn, :attributes => attrs)
182
+ end
183
+
184
+ it "create should return new entry on success, false on failure" do
185
+ pending "Need to Fix Ldap Permissions"
186
+
187
+ Namespace.find_by_cn(@cn).should be_nil
188
+ ns = add_entry(@cn)
189
+ ns.class.should == Namespace
190
+ ns.cn.should == [@cn]
191
+ ns.services.should == ['calnet']
192
+ add_entry(@cn).should be_false
193
+ end
194
+
195
+ it "create! should return new entry on success, raise error on failure" do
196
+ pending "Need to Fix Ldap Permissions"
197
+
198
+ Namespace.find_by_cn(@cn).should be_nil
199
+ ns = add_entry(@cn, 'calmail', "create!")
200
+ ns.should be_instance_of(Namespace)
201
+ ns.cn.should == [@cn]
202
+ lambda { add_entry(@cn, 'calnet', "create!") }.should raise_error(DirectoryNotUpdatedException)
203
+ end
204
+
205
+ it "update_attributes should return true on success, false on failure" do
206
+ pending "Need to Fix Ldap Permissions"
207
+
208
+ ns = add_entry(@cn)
209
+ ns.services.should == ['calnet']
210
+ ns.update_attributes(:berkeleyEduServices => ['calmail', 'calnet']).should be_true
211
+ ns.services.should == ['calmail', 'calnet']
212
+ ns.update_attributes(:berkeleyEduServices => ["calmail", "calmail"]).should be_false
213
+ end
214
+
215
+ it "update_attributes! should raise error on failure" do
216
+ pending "Need to Fix Ldap Permissions"
217
+
218
+ ns = add_entry(@cn)
219
+ ns.services.should == ['calnet']
220
+ ns.update_attributes!(:berkeleyEduServices => "calmail").should be_true
221
+ ns.services.should == ['calmail']
222
+ lambda { ns.update_attributes!(:berkeleyEduServices => ["calmail", "calmail"]) }.should raise_error(DirectoryNotUpdatedException)
223
+ end
224
+
225
+ it "delete should return true on success and false on failure" do
226
+ pending "Need to Fix Ldap Permissions"
227
+
228
+ ns = add_entry(@cn)
229
+ ns.delete.should be_true
230
+ ns.delete.should be_false
231
+ end
232
+
233
+ it "delete! should return true on success, raise DirectoryNotUpdated on failure" do
234
+ pending "Need to Fix Ldap Permissions"
235
+
236
+ ns = add_entry(@cn)
237
+ ns.delete!.should be_true
238
+ lambda { ns.delete! }.should raise_error(DirectoryNotUpdatedException)
239
+ end
240
+ end
241
+