socialcast 1.2.3 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +8 -8
  2. data/.travis.yml +1 -2
  3. data/bin/socialcast +2 -2
  4. data/lib/socialcast.rb +7 -15
  5. data/lib/socialcast/command_line/cli.rb +161 -0
  6. data/lib/socialcast/command_line/message.rb +18 -0
  7. data/lib/socialcast/command_line/provision.rb +330 -0
  8. data/lib/socialcast/command_line/version.rb +5 -0
  9. data/socialcast.gemspec +13 -10
  10. data/spec/fixtures/fake_attribute_map.rb +8 -6
  11. data/spec/fixtures/ldap_with_account_type_without_roles.yml +44 -0
  12. data/spec/fixtures/ldap_with_class_ldap_attribute.yml +47 -0
  13. data/spec/fixtures/ldap_with_connection_mapping.yml +52 -0
  14. data/spec/fixtures/ldap_with_connection_permission_mapping.yml +59 -0
  15. data/spec/fixtures/ldap_with_custom_attributes.yml +50 -0
  16. data/spec/fixtures/ldap_with_manager_attribute.yml +6 -3
  17. data/spec/fixtures/ldap_with_multiple_connection_mappings.yml +51 -0
  18. data/spec/fixtures/ldap_with_multiple_connection_permission_mappings.yml +75 -0
  19. data/spec/fixtures/ldap_with_plugin_mapping.yml +1 -1
  20. data/spec/fixtures/ldap_with_roles_without_account_type.yml +48 -0
  21. data/spec/fixtures/ldap_with_unique_identifier.yml +50 -0
  22. data/spec/fixtures/ldap_without_account_type_or_roles.yml +42 -0
  23. data/spec/{cli_spec.rb → socialcast/command_line/cli_spec.rb} +94 -82
  24. data/spec/socialcast/command_line/provision_spec.rb +497 -0
  25. data/spec/spec_helper.rb +2 -1
  26. metadata +103 -26
  27. data/lib/ext/array_ext.rb +0 -11
  28. data/lib/ext/string_ext.rb +0 -13
  29. data/lib/socialcast/cli.rb +0 -339
  30. data/lib/socialcast/message.rb +0 -17
  31. data/lib/socialcast/net_ldap_ext.rb +0 -87
  32. data/lib/socialcast/version.rb +0 -3
  33. data/spec/net_ldap_ext_spec.rb +0 -107
@@ -0,0 +1,497 @@
1
+ require 'spec_helper'
2
+
3
+ describe Socialcast::CommandLine::Provision do
4
+ let!(:credentials) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'credentials.yml')) }
5
+ let!(:ldap_default_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap.yml')) }
6
+ let!(:ldap_connection_mapping_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_connection_mapping.yml')) }
7
+ let!(:ldap_connection_permission_mapping_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_connection_permission_mapping.yml')) }
8
+ let!(:ldap_multiple_connection_mapping_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_multiple_connection_mappings.yml')) }
9
+ let!(:ldap_multiple_connection_permission_mapping_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_multiple_connection_permission_mappings.yml')) }
10
+ let!(:ldap_with_account_type_without_roles_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_account_type_without_roles.yml')) }
11
+ let!(:ldap_with_class_ldap_attribute_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_class_ldap_attribute.yml')) }
12
+ let!(:ldap_with_custom_attributes_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_custom_attributes.yml')) }
13
+ let!(:ldap_with_manager_attribute_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_manager_attribute.yml')) }
14
+ let!(:ldap_with_plugin_mapping_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_plugin_mapping.yml')) }
15
+ let!(:ldap_with_roles_without_account_type_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_roles_without_account_type.yml')) }
16
+ let!(:ldap_with_unique_identifier_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_with_unique_identifier.yml')) }
17
+ let!(:ldap_without_account_type_or_roles_config) { YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'fixtures', 'ldap_without_account_type_or_roles.yml')) }
18
+
19
+ def create_entry(entry_attributes)
20
+ Net::LDAP::Entry.new("dc=example,dc=com").tap do |e|
21
+ entry_attributes.each_pair do |attr, value|
22
+ e[attr] = value
23
+ end
24
+ end
25
+ end
26
+
27
+ describe "#provision" do
28
+ let(:result) { '' }
29
+
30
+ before do
31
+ Zlib::GzipWriter.stub(:open).and_yield(result)
32
+ Socialcast::CommandLine.stub(:credentials).and_return(credentials)
33
+ File.stub(:open).with(/users.xml.gz/, anything).and_yield(result)
34
+ end
35
+
36
+ context "when the entry has an email" do
37
+ before do
38
+ entry = create_entry :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name'
39
+ Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'isMemberOf'])).and_yield(entry)
40
+ RestClient::Resource.any_instance.should_receive(:post).once.with(hash_including(:file => result), { :accept => :json })
41
+
42
+ Socialcast::CommandLine::Provision.new(ldap_default_config, {}).provision
43
+ end
44
+ it "puts the user in the output file" do
45
+ result.should =~ /user@example.com/
46
+ end
47
+ end
48
+ context "when the entry has a unique_identifier" do
49
+ before do
50
+ entry = create_entry :uid => 'userID', :givenName => 'first name', :sn => 'last name'
51
+ Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'uid', 'isMemberOf'])).and_yield(entry)
52
+ RestClient::Resource.any_instance.should_receive(:post).once.with(hash_including(:file => result), { :accept => :json })
53
+
54
+ Socialcast::CommandLine::Provision.new(ldap_with_unique_identifier_config, {}).provision
55
+ end
56
+ it "puts the user in the output file" do
57
+ result.should =~ /userID/
58
+ end
59
+ end
60
+ context "when the entry has no email or unique_identifier" do
61
+ before do
62
+ entry = create_entry :mail => '', :givenName => 'first name', :sn => 'last name'
63
+ Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'isMemberOf'])).and_yield(entry)
64
+ RestClient::Resource.any_instance.should_not_receive(:post)
65
+ end
66
+ it "does not put the user in the output file" do
67
+ expect do
68
+ Socialcast::CommandLine::Provision.new(ldap_default_config, {}).provision
69
+ end.to raise_error(Socialcast::CommandLine::Provision::ProvisionError, "Skipping upload to Socialcast since no users were found")
70
+ end
71
+ end
72
+ context "attribute mappings" do
73
+ shared_examples "attributes are mapped properly" do
74
+ it do
75
+ users = Array.wrap(expected_attribute_xml).inject('') do |users_str, user_xml|
76
+ users_str << %Q[<user>
77
+ #{user_xml}
78
+ <account-type>member</account-type>
79
+ <roles type="array"/>
80
+ </user>]
81
+ end
82
+ result.gsub(/\s/, '').should == %Q[
83
+ <?xml version="1.0" encoding="UTF-8"?>
84
+ <export>
85
+ <users type="array">
86
+ #{users}
87
+ </users>
88
+ </export>
89
+ ].gsub(/\s/, '')
90
+ end
91
+ end
92
+
93
+ before do
94
+ RestClient::Resource.any_instance.should_receive(:post).once.with(hash_including(:file => result), { :accept => :json })
95
+ end
96
+
97
+ context "with mappings at the global level" do
98
+ before do
99
+ entry = create_entry :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name'
100
+ Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'isMemberOf'])).and_yield(entry)
101
+
102
+ Socialcast::CommandLine::Provision.new(ldap_default_config, {}).provision
103
+ end
104
+ let(:expected_attribute_xml) do
105
+ %Q[<first-name>first name</first-name>
106
+ <last-name>last name</last-name>
107
+ <contact-info>
108
+ <email>user@example.com</email>
109
+ </contact-info>
110
+ <custom-fields type="array"/>]
111
+ end
112
+ it_behaves_like "attributes are mapped properly"
113
+ end
114
+
115
+ context "with mappings at the connection level for one connection" do
116
+ before do
117
+ entry = create_entry :mailCon => 'user@example.com', :givenName => 'first name', :sn => 'last name'
118
+ Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['mailCon', 'isMemberOf'])).and_yield(entry)
119
+
120
+ Socialcast::CommandLine::Provision.new(ldap_connection_mapping_config, {}).provision
121
+ end
122
+ let(:expected_attribute_xml) do
123
+ %Q[<contact-info>
124
+ <email>user@example.com</email>
125
+ </contact-info>
126
+ <custom-fields type="array"/>]
127
+ end
128
+ it_behaves_like "attributes are mapped properly"
129
+ end
130
+
131
+ context "with mappings at the connection level for multiple connections" do
132
+ before do
133
+ provision_instance = Socialcast::CommandLine::Provision.new(ldap_multiple_connection_mapping_config, {})
134
+
135
+ ldap_instance1 = double
136
+ provision_instance.should_receive(:create_ldap_instance).once.ordered.and_return(ldap_instance1)
137
+ entry1 = create_entry :mailCon => 'user@example.com', :givenName => 'first name', :sn => 'last name'
138
+ ldap_instance1.should_receive(:search).once.with(hash_including(:attributes => ['mailCon', 'isMemberOf'])).and_yield(entry1)
139
+
140
+ ldap_instance2 = double
141
+ provision_instance.should_receive(:create_ldap_instance).once.ordered.and_return(ldap_instance2)
142
+ entry2 = create_entry :mailCon2 => 'user2@example.com', :firstName => 'first name2', :sn => 'last name2'
143
+ ldap_instance2.should_receive(:search).once.with(hash_including(:attributes => ['mailCon2', 'firstName', 'isMemberOf'])).and_yield(entry2)
144
+
145
+ provision_instance.provision
146
+ end
147
+ let(:expected_attribute_xml) do
148
+ [%Q[<contact-info>
149
+ <email>user@example.com</email>
150
+ </contact-info>
151
+ <custom-fields type="array"/>],
152
+ %Q[<first-name>first name2</first-name>
153
+ <contact-info>
154
+ <email>user2@example.com</email>
155
+ </contact-info>
156
+ <custom-fields type="array"/>]
157
+ ]
158
+ end
159
+ it_behaves_like "attributes are mapped properly"
160
+ end
161
+
162
+ context "with custom attribute mappings" do
163
+ before do
164
+ entry = create_entry :mail => 'user@example.com', :custom_ldap1 => 'custom value 1', :custom_ldap2 => 'custom value 2'
165
+ Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['custom_ldap1', 'custom_ldap2', 'mail', 'isMemberOf'])).and_yield(entry)
166
+
167
+ Socialcast::CommandLine::Provision.new(ldap_with_custom_attributes_config, {}).provision
168
+ end
169
+ let(:expected_attribute_xml) do
170
+ %Q[<contact-info>
171
+ <email>user@example.com</email>
172
+ </contact-info>
173
+ <custom-fields type="array">
174
+ <custom-field>
175
+ <id>custom_attr1</id>
176
+ <label>custom_attr1</label>
177
+ <value>custom value 1</value>
178
+ </custom-field>
179
+ <custom-field>
180
+ <id>custom_attr2</id>
181
+ <label>custom_attr2</label>
182
+ <value>custom value 2</value>
183
+ </custom-field>
184
+ </custom-fields>]
185
+ end
186
+ it_behaves_like "attributes are mapped properly"
187
+ end
188
+
189
+ context "with manager" do
190
+ before do
191
+ provision_instance = Socialcast::CommandLine::Provision.new(ldap_with_manager_attribute_config, {})
192
+
193
+ ldap_instance = double
194
+ provision_instance.should_receive(:create_ldap_instance).once.ordered.and_return(ldap_instance)
195
+
196
+ user_entry = create_entry :mail => 'user@example.com', :ldap_manager => 'cn=theboss,dc=example,dc=com'
197
+ manager_entry = create_entry :mail => 'boss@example.com'
198
+ ldap_instance.should_receive(:search).once.ordered.with(hash_including(:attributes => ['mail', 'ldap_manager', 'isMemberOf'])).and_yield(user_entry)
199
+ ldap_instance.should_receive(:search).once.ordered.and_yield(manager_entry)
200
+
201
+ provision_instance.provision
202
+ end
203
+ let(:expected_attribute_xml) do
204
+ %Q[<contact-info>
205
+ <email>user@example.com</email>
206
+ </contact-info>
207
+ <custom-fields type="array">
208
+ <custom-field>
209
+ <id>manager_email</id>
210
+ <label>manager_email</label>
211
+ <value>boss@example.com</value>
212
+ </custom-field>
213
+ </custom-fields>]
214
+ end
215
+ it_behaves_like "attributes are mapped properly"
216
+ end
217
+
218
+ context "with an ldap mapping that has the same name as a class" do
219
+ before do
220
+ module TestLdapAttributeMapping end
221
+ entry = create_entry :test_ldap_attribute_mapping => 'user@example.com'
222
+ Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['test_ldap_attribute_mapping', 'isMemberOf'])).and_yield(entry)
223
+
224
+ Socialcast::CommandLine::Provision.new(ldap_with_class_ldap_attribute_config, {}).provision
225
+ end
226
+ after do
227
+ Object.send(:remove_const, :TestLdapAttributeMapping)
228
+ end
229
+ let(:expected_attribute_xml) do
230
+ %Q[<contact-info>
231
+ <email>user@example.com</email>
232
+ </contact-info>
233
+ <custom-fields type="array"/>]
234
+ end
235
+ it_behaves_like "attributes are mapped properly"
236
+ end
237
+ end
238
+ context "permission attribute mappings" do
239
+ shared_examples "permission attributes are mapped properly" do
240
+ it do
241
+ users = Array.wrap(expected_permission_xml).inject('') do |users_str, permission_xml|
242
+ users_str << %Q[<user>
243
+ <first-name>first name</first-name>
244
+ <last-name>last name</last-name>
245
+ <contact-info>
246
+ <email>user@example.com</email>
247
+ </contact-info>
248
+ <custom-fields type="array"/>
249
+ #{permission_xml}
250
+ </user>]
251
+ end
252
+ result.gsub(/\s/, '').should == %Q[
253
+ <?xml version="1.0" encoding="UTF-8"?>
254
+ <export>
255
+ <users type="array">
256
+ #{users}
257
+ </users>
258
+ </export>
259
+ ].gsub(/\s/, '')
260
+ end
261
+ end
262
+
263
+ let(:entry) { create_entry :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name', :isMemberOf => ldap_groups }
264
+ let(:ldap_group_attribute) { 'isMemberOf' }
265
+
266
+ before do
267
+ RestClient::Resource.any_instance.should_receive(:post).once.with(hash_including(:file => result), { :accept => :json })
268
+ end
269
+
270
+ context "with roles for an external contributor" do
271
+ let(:ldap_groups) { ["cn=External,dc=example,dc=com", "cn=SbiAdmins,dc=example,dc=com", "cn=TownHallAdmins,dc=example,dc=com"] }
272
+ before do
273
+ Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', ldap_group_attribute])).and_yield(entry)
274
+ Socialcast::CommandLine::Provision.new(ldap_default_config, {}).provision
275
+ end
276
+ let(:expected_permission_xml) do
277
+ %Q[<account-type>external</account-type>]
278
+ end
279
+ it_behaves_like "permission attributes are mapped properly"
280
+ end
281
+
282
+ context "with roles for a member" do
283
+ let(:ldap_groups) { ["cn=SbiAdmins,dc=example,dc=com", "cn=TownHallAdmins,dc=example,dc=com"] }
284
+ before do
285
+ Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', ldap_group_attribute])).and_yield(entry)
286
+ Socialcast::CommandLine::Provision.new(ldap_default_config, {}).provision
287
+ end
288
+ let(:expected_permission_xml) do
289
+ %Q[<account-type>member</account-type>
290
+ <roles type="array">
291
+ <role>sbi_admin</role>
292
+ <role>town_hall_admin</role>
293
+ </roles>]
294
+ end
295
+ it_behaves_like "permission attributes are mapped properly"
296
+ end
297
+
298
+ context "with account_types mapping and no role mappings" do
299
+ let(:ldap_groups) { ["cn=SbiAdmins,dc=example,dc=com", "cn=TownHallAdmins,dc=example,dc=com"] }
300
+ before do
301
+ Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', ldap_group_attribute])).and_yield(entry)
302
+ Socialcast::CommandLine::Provision.new(ldap_with_account_type_without_roles_config, {}).provision
303
+ end
304
+ let(:expected_permission_xml) do
305
+ %Q[<account-type>member</account-type>]
306
+ end
307
+ it_behaves_like "permission attributes are mapped properly"
308
+ end
309
+
310
+ context "with role mappings and no account_type mapping" do
311
+ let(:ldap_groups) { ["cn=SbiAdmins,dc=example,dc=com", "cn=TownHallAdmins,dc=example,dc=com"] }
312
+ before do
313
+ Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', ldap_group_attribute])).and_yield(entry)
314
+ Socialcast::CommandLine::Provision.new(ldap_with_roles_without_account_type_config, {}).provision
315
+ end
316
+ let(:expected_permission_xml) do
317
+ %Q[<account-type>member</account-type>
318
+ <roles type="array">
319
+ <role>sbi_admin</role>
320
+ <role>town_hall_admin</role>
321
+ </roles>]
322
+ end
323
+ it_behaves_like "permission attributes are mapped properly"
324
+ end
325
+
326
+ context "without account_type or roles mappings" do
327
+ let(:ldap_groups) { ["cn=SbiAdmins,dc=example,dc=com", "cn=TownHallAdmins,dc=example,dc=com"] }
328
+ before do
329
+ Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', ldap_group_attribute])).and_yield(entry)
330
+ Socialcast::CommandLine::Provision.new(ldap_without_account_type_or_roles_config, {}).provision
331
+ end
332
+ let(:expected_permission_xml) do
333
+ %Q[<account-type>member</account-type>]
334
+ end
335
+ it_behaves_like "permission attributes are mapped properly"
336
+ end
337
+
338
+ context "with permission mappings at the connection level for one connection" do
339
+ let(:ldap_group_attribute) { 'memberOf' }
340
+ let(:ldap_groups) { ["cn=External,dc=example,dc=com", "cn=SbiAdmins,dc=example,dc=com", "cn=TownHallAdmins,dc=example,dc=com"] }
341
+ let(:entry) { create_entry :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name', :memberOf => ldap_groups }
342
+ before do
343
+ Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', ldap_group_attribute])).and_yield(entry)
344
+ Socialcast::CommandLine::Provision.new(ldap_connection_permission_mapping_config, {}).provision
345
+ end
346
+ let(:expected_permission_xml) do
347
+ %Q[<account-type>member</account-type>
348
+ <roles type="array">
349
+ <role>reach_admin</role>
350
+ </roles>]
351
+ end
352
+ it_behaves_like "permission attributes are mapped properly"
353
+ end
354
+
355
+ context "with permission mappings at the connection level for multiple connections" do
356
+ let(:ldap_group_attribute) { 'memberOf' }
357
+ let(:ldap_groups) { }
358
+ before do
359
+ provision_instance = Socialcast::CommandLine::Provision.new(ldap_multiple_connection_permission_mapping_config, {})
360
+
361
+ ldap_instance1 = double
362
+ provision_instance.should_receive(:create_ldap_instance).once.ordered.and_return(ldap_instance1)
363
+ entry1 = create_entry :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name', :memberOf => ["cn=External,dc=example,dc=com", "cn=SbiAdmins,dc=example,dc=com", "cn=TownHallAdmins,dc=example,dc=com"]
364
+ ldap_instance1.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'memberOf'])).and_yield(entry1)
365
+
366
+ ldap_instance2 = double
367
+ provision_instance.should_receive(:create_ldap_instance).once.ordered.and_return(ldap_instance2)
368
+ entry2 = create_entry :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name', :member => ["cn=Contractors,dc=example,dc=com", "cn=SbiAdmins,dc=example,dc=com", "cn=TownHallAdmins,dc=example,dc=com"]
369
+ ldap_instance2.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'member'])).and_yield(entry2)
370
+
371
+ provision_instance.provision
372
+ end
373
+ let(:expected_permission_xml) do
374
+ [%Q[<account-type>member</account-type>
375
+ <roles type="array">
376
+ <role>reach_admin</role>
377
+ </roles>],
378
+ %Q[<account-type>member</account-type>
379
+ <roles type="array">
380
+ <role>sbi_admin</role>
381
+ </roles>]]
382
+ end
383
+ it_behaves_like "permission attributes are mapped properly"
384
+ end
385
+ end
386
+ end
387
+
388
+ describe '#dereference_mail' do
389
+ context "called on directreport entry" do
390
+ let(:entry) do
391
+ Net::LDAP::Entry.new("cn=directreport,dc=example,dc=com").tap do |e|
392
+ e[:mail] = 'directreport@example.com'
393
+ e[:manager] = 'cn=bossman,dc=example,dc=com'
394
+ end
395
+ end
396
+ let(:ldap) { double('net/ldap') }
397
+ before do
398
+ manager_entry = Net::LDAP::Entry.new("cn=bossman,dc=example,dc=com")
399
+ manager_entry[:mail] = 'bossman@example.com'
400
+ ldap.should_receive(:search).with(:base => "cn=bossman,dc=example,dc=com", :scope => 0).and_yield(manager_entry)
401
+ end
402
+ it "will return bossman email" do
403
+ Socialcast::CommandLine::Provision.new(ldap_default_config, {}).send(:dereference_mail, entry, ldap, 'manager', 'mail').should == "bossman@example.com"
404
+ end
405
+ end
406
+ end
407
+
408
+ describe "#each_user_hash" do
409
+ let(:provision_instance) { Socialcast::CommandLine::Provision.new(ldap_default_config, :plugins => 'socialcast/command_line/fake_attribute_map') }
410
+ before do
411
+ entry = create_entry :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name'
412
+ Net::LDAP.any_instance.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'isMemberOf'])).and_yield(entry)
413
+ end
414
+ it do
415
+ expect do |blk|
416
+ provision_instance.each_user_hash(&blk)
417
+ end.to yield_with_args(HashWithIndifferentAccess.new({
418
+ 'first_name' => 'first name',
419
+ 'last_name' => 'last name',
420
+ 'contact_info' => {
421
+ 'email' => 'user@example.com',
422
+ },
423
+ 'custom_fields' => [],
424
+ 'account_type' => 'member',
425
+ 'roles' => []
426
+ }))
427
+ end
428
+ end
429
+
430
+ describe "#grab" do
431
+ let(:provision_instance) { Socialcast::CommandLine::Provision.new(ldap_with_plugin_mapping_config, :plugins => 'socialcast/command_line/fake_attribute_map') }
432
+ let(:entry) do
433
+ Net::LDAP::Entry.new("cn=sean,dc=example,dc=com").tap do |e|
434
+ e[:mail] = 'sean@example.com'
435
+ end
436
+ end
437
+ context "passed hash for attribute" do
438
+ it "returns a string that used defined string template" do
439
+ provision_instance.send(:grab, entry, { "value" => "123%{mail}", "mail" => "mail" }).should == "123sean@example.com"
440
+ end
441
+ end
442
+ context "passed string for attribute" do
443
+ it "returns exact string stored in entry" do
444
+ provision_instance.send(:grab, entry, "mail").should == "sean@example.com"
445
+ end
446
+ end
447
+ context "passed string that can be constantized and the resulting Class responds to run" do
448
+ it "returns result of run method" do
449
+ module Socialcast::CommandLine
450
+ class FakeAttributeMap
451
+ def self.run(entry)
452
+ return "#{entry[:mail].first.gsub(/a/,'b')}"
453
+ end
454
+ end
455
+ end
456
+ provision_instance.send(:grab, entry, "Socialcast::CommandLine::FakeAttributeMap").should == "sebn@exbmple.com"
457
+ end
458
+ end
459
+ context "passed string that must be classified and the resulting Class responds to run" do
460
+ it "returns result of run method" do
461
+ module Socialcast::CommandLine
462
+ class FakeAttributeMap
463
+ def self.run(entry)
464
+ return "#{entry[:mail].first.gsub(/a/,'b')}"
465
+ end
466
+ end
467
+ end
468
+ provision_instance.send(:grab, entry, "socialcast/command_line/fake_attribute_map").should == "sebn@exbmple.com"
469
+ end
470
+ end
471
+ context "attribute passed has a collision between string and Class" do
472
+ before do
473
+ class Mail
474
+ def self.run(entry)
475
+ return "#{entry[:mail].first.gsub(/a/,'b')}"
476
+ end
477
+ end
478
+ end
479
+ after do
480
+ Object.send(:remove_const, :Mail)
481
+ end
482
+ it "returns the result of the Class run method" do
483
+ provision_instance.send(:grab, entry, "mail").should == "sebn@exbmple.com"
484
+ end
485
+ end
486
+ context "attribute passed constantizes to a module instead of a class" do
487
+ it "returns the result of the Module run method" do
488
+ module FakeAttributeMap
489
+ def self.run(entry)
490
+ return "#{entry[:mail].first.gsub(/a/,'b')}"
491
+ end
492
+ end
493
+ provision_instance.send(:grab, entry, "FakeAttributeMap").should == "sebn@exbmple.com"
494
+ end
495
+ end
496
+ end
497
+ end