socialcast 1.3.11 → 1.3.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/socialcast/command_line/ldap_connector.rb +86 -65
- data/lib/socialcast/command_line/provisioner.rb +8 -4
- data/lib/socialcast/command_line/version.rb +1 -1
- data/spec/socialcast/command_line/cli_spec.rb +1 -1
- data/spec/socialcast/command_line/ldap_connector_spec.rb +135 -25
- data/spec/socialcast/command_line/provision_photo_spec.rb +3 -3
- data/spec/socialcast/command_line/provision_user_spec.rb +11 -11
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 610338f9bd0ce308510f29fe684fc4ed7f876fd4
|
4
|
+
data.tar.gz: 67eadbc1549337bbc9c0bafeaa4f934c8f9d1d70
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bbc659eefaace5269780c1052706eb9fe860f3e585bff2d23353b58924c331533e1005eb11d1546b98b5a30b403fd6e5593f943bf4b0da958c07247ec308692b
|
7
|
+
data.tar.gz: c85326a13ca5c7c637e70b474497a1827c05a9f5f370859b29eb311f52f171e922ca7c01161670f84d895be36d3800662eb32bbe20ecaed017ec78b25c56c4f4
|
@@ -5,6 +5,8 @@ require 'active_support/core_ext/array/wrap'
|
|
5
5
|
module Socialcast
|
6
6
|
module CommandLine
|
7
7
|
class LDAPConnector
|
8
|
+
class ConcurrentSearchError < StandardError; end
|
9
|
+
|
8
10
|
UNIQUE_IDENTIFIER_ATTRIBUTE = "unique_identifier"
|
9
11
|
EMAIL_ATTRIBUTE = "email"
|
10
12
|
MANAGER_ATTRIBUTE = "manager"
|
@@ -14,66 +16,65 @@ module Socialcast
|
|
14
16
|
|
15
17
|
attr_reader :attribute_mappings, :connection_name
|
16
18
|
|
17
|
-
def self.with_connector(connection_name, config)
|
18
|
-
connection_config = config["connections"][connection_name]
|
19
|
-
ldap = Net::LDAP.new(:host => connection_config["host"], :port => connection_config["port"], :base => connection_config["basedn"]).tap do |ldap_instance|
|
20
|
-
ldap_instance.encryption connection_config['encryption'].to_sym if connection_config['encryption']
|
21
|
-
ldap_instance.auth connection_config["username"], connection_config["password"]
|
22
|
-
end
|
23
|
-
|
24
|
-
ldap.open do |connected_ldap_instance|
|
25
|
-
yield new(connection_name, config, connected_ldap_instance)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
19
|
def self.attribute_mappings_for(connection_name, config)
|
30
20
|
config['connections'][connection_name]['mappings'] || config.fetch('mappings', {})
|
31
21
|
end
|
32
22
|
|
33
|
-
def initialize(connection_name, config
|
23
|
+
def initialize(connection_name, config)
|
34
24
|
@connection_name = connection_name
|
35
25
|
@config = config
|
36
|
-
@ldap = ldap
|
37
|
-
@group_unique_identifiers = fetch_group_unique_identifiers
|
38
|
-
@dn_to_email_hash = fetch_dn_to_email_hash
|
39
26
|
end
|
40
27
|
|
41
28
|
def each_user_hash
|
42
|
-
|
43
|
-
|
29
|
+
ldap.open do
|
30
|
+
fetch_group_unique_identifiers
|
31
|
+
fetch_dn_to_email_hash
|
32
|
+
|
33
|
+
each_ldap_entry(ldap_user_search_attributes) do |entry|
|
34
|
+
yield build_user_hash_from_mappings(entry)
|
35
|
+
end
|
44
36
|
end
|
45
37
|
end
|
46
38
|
|
47
39
|
def each_photo_hash
|
48
|
-
|
49
|
-
|
50
|
-
|
40
|
+
ldap.open do
|
41
|
+
each_ldap_entry(ldap_photo_search_attributes) do |entry|
|
42
|
+
photo_hash = build_photo_hash_from_mappings(entry)
|
43
|
+
yield photo_hash if photo_hash.present?
|
44
|
+
end
|
51
45
|
end
|
52
46
|
end
|
53
47
|
|
54
48
|
def fetch_user_hash(identifier, options)
|
55
|
-
|
56
|
-
|
49
|
+
ldap.open do
|
50
|
+
fetch_group_unique_identifiers
|
51
|
+
fetch_dn_to_email_hash
|
57
52
|
|
58
|
-
|
59
|
-
|
60
|
-
else
|
61
|
-
Net::LDAP::Filter.pres("objectclass")
|
62
|
-
end
|
53
|
+
options = options.dup
|
54
|
+
identifying_field = options.delete(:identifying_field) || UNIQUE_IDENTIFIER_ATTRIBUTE
|
63
55
|
|
64
|
-
|
56
|
+
filter = if connection_config['filter'].present?
|
57
|
+
Net::LDAP::Filter.construct(connection_config['filter'])
|
58
|
+
else
|
59
|
+
Net::LDAP::Filter.pres("objectclass")
|
60
|
+
end
|
65
61
|
|
66
|
-
|
67
|
-
return build_user_hash_from_mappings(entry)
|
68
|
-
end
|
62
|
+
filter = filter & Net::LDAP::Filter.construct("#{attribute_mappings[identifying_field]}=#{identifier}")
|
69
63
|
|
70
|
-
|
64
|
+
search(:base => connection_config['basedn'], :filter => filter, :attributes => ldap_user_search_attributes, :size => 1) do |entry|
|
65
|
+
return build_user_hash_from_mappings(entry)
|
66
|
+
end
|
67
|
+
|
68
|
+
nil
|
69
|
+
end
|
71
70
|
end
|
72
71
|
|
73
72
|
def attribute_mappings
|
74
73
|
@attribute_mappings ||= LDAPConnector.attribute_mappings_for(@connection_name, @config)
|
75
74
|
end
|
76
75
|
|
76
|
+
private
|
77
|
+
|
77
78
|
# grab a *single* value of an attribute
|
78
79
|
# abstracts away ldap multivalue attributes
|
79
80
|
def grab(entry, attribute)
|
@@ -99,7 +100,16 @@ module Socialcast
|
|
99
100
|
end
|
100
101
|
end
|
101
102
|
|
102
|
-
|
103
|
+
def ldap
|
104
|
+
@ldap ||= Net::LDAP.new(:host => connection_config["host"], :port => connection_config["port"], :base => connection_config["basedn"]).tap do |ldap_instance|
|
105
|
+
ldap_instance.encryption connection_config['encryption'].to_sym if connection_config['encryption']
|
106
|
+
ldap_instance.auth connection_config["username"], connection_config["password"]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def root_namingcontexts
|
111
|
+
@root_naming_contexts ||= Array.wrap(@ldap.search_root_dse.namingcontexts)
|
112
|
+
end
|
103
113
|
|
104
114
|
def each_ldap_entry(attributes)
|
105
115
|
search(:return_result => false, :filter => connection_config["filter"], :base => connection_config["basedn"], :attributes => attributes) do |entry|
|
@@ -156,17 +166,24 @@ module Socialcast
|
|
156
166
|
end
|
157
167
|
|
158
168
|
def search(search_options)
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
+
raise ConcurrentSearchError.new "Cannot perform concurrent searches on an open ldap connection" if @search_in_progress
|
170
|
+
begin
|
171
|
+
options_for_search = if search_options[:base].present?
|
172
|
+
Array.wrap(search_options)
|
173
|
+
else
|
174
|
+
options_for_search = root_namingcontexts.map { |dn| search_options.merge(:base => dn ) }
|
175
|
+
end
|
176
|
+
|
177
|
+
options_for_search.each do |options|
|
178
|
+
@search_in_progress = true
|
179
|
+
|
180
|
+
@ldap.search(options) do |entry|
|
181
|
+
yield(entry)
|
182
|
+
end
|
183
|
+
|
169
184
|
end
|
185
|
+
ensure
|
186
|
+
@search_in_progress = false
|
170
187
|
end
|
171
188
|
end
|
172
189
|
|
@@ -190,30 +207,34 @@ module Socialcast
|
|
190
207
|
end
|
191
208
|
|
192
209
|
def fetch_group_unique_identifiers
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
210
|
+
@group_unique_identifiers ||= if group_membership_mappings.present?
|
211
|
+
{}.tap do |groups|
|
212
|
+
search_options = {
|
213
|
+
:return_result => false,
|
214
|
+
:filter => group_membership_mappings["filter"],
|
215
|
+
:base => connection_config["basedn"],
|
216
|
+
:attributes => [group_membership_mappings[UNIQUE_IDENTIFIER_ATTRIBUTE]]
|
217
|
+
}
|
218
|
+
|
219
|
+
search(search_options) do |entry|
|
220
|
+
groups[grab(entry, "dn")] = grab(entry, group_membership_mappings[UNIQUE_IDENTIFIER_ATTRIBUTE])
|
221
|
+
end
|
222
|
+
end
|
223
|
+
else
|
224
|
+
{}
|
225
|
+
end
|
207
226
|
end
|
208
227
|
|
209
228
|
def fetch_dn_to_email_hash
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
229
|
+
@dn_to_email_hash ||= if attribute_mappings[MANAGER_ATTRIBUTE].present?
|
230
|
+
{}.tap do |dn_to_email_hash|
|
231
|
+
each_ldap_entry(ldap_mail_search_attributes) do |entry|
|
232
|
+
dn_to_email_hash[entry.dn] = grab(entry, attribute_mappings[EMAIL_ATTRIBUTE])
|
233
|
+
end
|
234
|
+
end
|
235
|
+
else
|
236
|
+
{}
|
237
|
+
end
|
217
238
|
end
|
218
239
|
|
219
240
|
def add_primary_attributes(entry, user_hash)
|
@@ -18,11 +18,15 @@ module Socialcast
|
|
18
18
|
@http_config ||= @ldap_config.fetch 'http', {}
|
19
19
|
end
|
20
20
|
|
21
|
+
def ldap_connectors
|
22
|
+
@ldap_connectors ||= @ldap_config['connections'].map do |connection_name, _|
|
23
|
+
LDAPConnector.new(connection_name, @ldap_config)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
21
27
|
def each_ldap_connector
|
22
|
-
|
23
|
-
|
24
|
-
yield ldap_connector
|
25
|
-
end
|
28
|
+
ldap_connectors.each do |ldap_connector|
|
29
|
+
yield ldap_connector
|
26
30
|
end
|
27
31
|
end
|
28
32
|
|
@@ -21,7 +21,7 @@ describe Socialcast::CommandLine::CLI do
|
|
21
21
|
|
22
22
|
let(:ldap) do
|
23
23
|
ldap_instance = double(Net::LDAP, :auth => nil, :encryption => nil)
|
24
|
-
ldap_instance.should_receive(:open).and_yield
|
24
|
+
ldap_instance.should_receive(:open).and_yield
|
25
25
|
Net::LDAP.should_receive(:new).and_return(ldap_instance)
|
26
26
|
ldap_instance
|
27
27
|
end
|
@@ -49,6 +49,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
49
49
|
let(:ldap) { double(Net::LDAP, :open => nil, :encryption => nil, :auth => nil) }
|
50
50
|
|
51
51
|
before do
|
52
|
+
ldap.stub(:open).and_yield
|
52
53
|
Net::LDAP.stub(:new).and_return(ldap)
|
53
54
|
end
|
54
55
|
|
@@ -62,7 +63,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
62
63
|
|
63
64
|
describe "#each_user_hash" do
|
64
65
|
context "when the entry has an email" do
|
65
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
66
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
66
67
|
let(:entry) { create_entry('user', :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name') }
|
67
68
|
before do
|
68
69
|
ldap.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'isMemberOf'])).and_yield(entry)
|
@@ -84,7 +85,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
84
85
|
end
|
85
86
|
|
86
87
|
context("when the entry does not have a unique_identifier or email") do
|
87
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
88
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
88
89
|
let(:entry) { create_entry('user', :mail => nil, :givenName => 'first name', :sn => 'last name') }
|
89
90
|
before do
|
90
91
|
ldap.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'isMemberOf'])).and_yield(entry)
|
@@ -104,7 +105,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
104
105
|
"unique_identifier" => "uid"
|
105
106
|
}
|
106
107
|
end
|
107
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
108
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
108
109
|
let(:entry) { create_entry('user', :uid => 'unique identifier', :givenName => 'first name', :sn => 'last name') }
|
109
110
|
before do
|
110
111
|
ldap.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'uid', 'isMemberOf'])).and_yield(entry)
|
@@ -125,7 +126,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
125
126
|
end
|
126
127
|
|
127
128
|
context "when the entry has a profile photo" do
|
128
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
129
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
129
130
|
let(:entry) { create_entry('user', :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name') }
|
130
131
|
let(:mappings) do
|
131
132
|
{
|
@@ -155,7 +156,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
155
156
|
end
|
156
157
|
|
157
158
|
context "when the entry has a manager" do
|
158
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
159
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
159
160
|
let(:employee_entry) { create_entry('user', :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name', :manager_dn => 'cn=manager,dc=example,dc=com') }
|
160
161
|
let(:manager_entry) { create_entry('manager', :mail => 'manager@example.com', :givenName => 'manager first name', :sn => 'manager last name') }
|
161
162
|
let(:employee_mail_entry) { create_entry('user', :mail => 'user@example.com') }
|
@@ -212,7 +213,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
212
213
|
end
|
213
214
|
|
214
215
|
context "with multiple manager entries" do
|
215
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
216
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
216
217
|
let(:employee_entry1) { create_entry('user1', :mail => 'user1@example.com', :givenName => 'first name1', :sn => 'last name1', :manager_dn => 'cn=manager1,dc=example,dc=com') }
|
217
218
|
let(:employee_entry2) { create_entry('user2', :mail => 'user2@example.com', :givenName => 'first name2', :sn => 'last name2', :manager_dn => 'cn=manager2,dc=example,dc=com') }
|
218
219
|
let(:employee_entry3) { create_entry('user3', :mail => 'user3@example.com', :givenName => 'first name3', :sn => 'last name3', :manager_dn => 'cn=manager1,dc=example,dc=com') }
|
@@ -324,7 +325,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
324
325
|
end
|
325
326
|
|
326
327
|
context "with attribute mappings at the connection level" do
|
327
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
328
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
328
329
|
before do
|
329
330
|
connection.merge!({ "mappings" => { "email" => "mailConnection" } })
|
330
331
|
entry = create_entry 'user', :mailConnection => 'user@example.com'
|
@@ -344,7 +345,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
344
345
|
end
|
345
346
|
end
|
346
347
|
context "with permission mappings at the connection level" do
|
347
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
348
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
348
349
|
let(:ldap_groups) { ["cn=External,dc=example,dc=com", "cn=BizAdmins,dc=example,dc=com", "cn=TownHallAdmins,dc=example,dc=com"] }
|
349
350
|
before do
|
350
351
|
connection.merge!({
|
@@ -379,7 +380,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
379
380
|
end
|
380
381
|
end
|
381
382
|
context "with external ldap group memberships" do
|
382
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
383
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
383
384
|
let(:entry) do
|
384
385
|
create_entry('user', :mail => 'user@example.com',
|
385
386
|
:givenName => 'first name',
|
@@ -404,7 +405,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
404
405
|
end
|
405
406
|
end
|
406
407
|
context "with role ldap group memberships" do
|
407
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
408
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
408
409
|
let(:entry) do
|
409
410
|
create_entry('user', :mail => 'user@example.com',
|
410
411
|
:givenName => 'first name',
|
@@ -436,7 +437,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
436
437
|
"unique_identifier" => "gid"
|
437
438
|
}
|
438
439
|
end
|
439
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
440
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
440
441
|
let(:group_entry1) do
|
441
442
|
create_entry('group1', :dn => "cn=Sales,dc=example,dc=com", :gid => "sales_group_id")
|
442
443
|
end
|
@@ -481,11 +482,49 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
481
482
|
}))
|
482
483
|
end
|
483
484
|
end
|
485
|
+
|
486
|
+
context "calling when a search is already being performed" do
|
487
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
488
|
+
before do
|
489
|
+
ldap.should_receive(:search).and_yield(create_entry('user', :mail => 'user@example.com'))
|
490
|
+
end
|
491
|
+
it "raises an error" do
|
492
|
+
expect do
|
493
|
+
connector.each_user_hash do |user_hash|
|
494
|
+
connector.each_user_hash do |another_user_hash|
|
495
|
+
# connection already open
|
496
|
+
end
|
497
|
+
end
|
498
|
+
end.to raise_error Socialcast::CommandLine::LDAPConnector::ConcurrentSearchError
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
context "calling when a search is already being performed, rescuing, then calling again" do
|
503
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
504
|
+
before do
|
505
|
+
ldap.should_receive(:search).and_yield(create_entry('user', :mail => 'user@example.com'))
|
506
|
+
end
|
507
|
+
it "raises an error" do
|
508
|
+
expect do
|
509
|
+
connector.each_user_hash do |user_hash|
|
510
|
+
begin
|
511
|
+
connector.each_user_hash do |another_user_hash|
|
512
|
+
# connection already open
|
513
|
+
end
|
514
|
+
rescue Socialcast::CommandLine::LDAPConnector::ConcurrentSearchError
|
515
|
+
end
|
516
|
+
connector.each_user_hash do |another_user_hash|
|
517
|
+
# connection already open
|
518
|
+
end
|
519
|
+
end
|
520
|
+
end.to raise_error Socialcast::CommandLine::LDAPConnector::ConcurrentSearchError
|
521
|
+
end
|
522
|
+
end
|
484
523
|
end
|
485
524
|
|
486
525
|
describe "#each_photo_hash" do
|
487
526
|
context "when the entry has an email and photo" do
|
488
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
527
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
489
528
|
let(:entry) { create_entry('user', :mail => 'user@example.com', :jpegPhoto => "photo") }
|
490
529
|
let(:mappings) do
|
491
530
|
{
|
@@ -508,7 +547,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
508
547
|
end
|
509
548
|
end
|
510
549
|
context "when the entry does not have an email" do
|
511
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
550
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
512
551
|
let(:entry) { create_entry('user', :mail => '', :jpegPhoto => "photo") }
|
513
552
|
let(:mappings) do
|
514
553
|
{
|
@@ -530,7 +569,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
530
569
|
end
|
531
570
|
|
532
571
|
context "when the entry does not have a photo" do
|
533
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
572
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
534
573
|
let(:entry) { create_entry('user', :mail => 'user@example.com', :jpegPhoto => "") }
|
535
574
|
let(:mappings) do
|
536
575
|
{
|
@@ -552,7 +591,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
552
591
|
end
|
553
592
|
|
554
593
|
context "when the entry has a binary photo with incorrect encoding" do
|
555
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
594
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
556
595
|
let(:entry) { create_entry('user', :mail => 'user@example.com', :jpegPhoto => "\x89PNGabc") }
|
557
596
|
let(:mappings) do
|
558
597
|
{
|
@@ -585,7 +624,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
585
624
|
"unique_identifier" => "uid"
|
586
625
|
}
|
587
626
|
end
|
588
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
627
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
589
628
|
let(:entry) { create_entry 'user', :uid => 'unique identifier', :givenName => 'first name', :sn => 'last name' }
|
590
629
|
before do
|
591
630
|
filter = Net::LDAP::Filter.construct('(&(mail=*)(uid=unique identifier))')
|
@@ -605,8 +644,9 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
605
644
|
}
|
606
645
|
end
|
607
646
|
end
|
647
|
+
|
608
648
|
context "specifying an identifying field" do
|
609
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
649
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
610
650
|
let(:entry) { create_entry 'user', :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name' }
|
611
651
|
before do
|
612
652
|
filter = Net::LDAP::Filter.construct('(&(mail=*)(mail=user@example.com))')
|
@@ -630,7 +670,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
630
670
|
|
631
671
|
context "without a filter specified" do
|
632
672
|
let(:filter) { "" }
|
633
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
673
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
634
674
|
let(:entry) { create_entry 'user', :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name' }
|
635
675
|
before do
|
636
676
|
filter = Net::LDAP::Filter.construct('(&(objectclass=*)(mail=user@example.com))')
|
@@ -651,6 +691,76 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
651
691
|
}
|
652
692
|
end
|
653
693
|
end
|
694
|
+
|
695
|
+
context "calling more than once with managers and groups configured" do
|
696
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
697
|
+
let(:manager) { create_entry('manager', :mail => 'manager@example.com', :givenName => 'manager first name', :sn => 'manager last name') }
|
698
|
+
let(:user1) { create_entry 'user1', :mail => 'user1@example.com', :givenName => 'first name 1', :sn => 'last name 1', :isMemberOf => [] }
|
699
|
+
let(:user2) { create_entry 'user2', :mail => 'user2@example.com', :givenName => 'first name 2', :sn => 'last name 2', :isMemberOf => ["cn=Sales,dc=example,dc=com"] }
|
700
|
+
let(:group) { create_entry('group', :dn => "cn=Sales,dc=example,dc=com", :gid => "sales_group_id") }
|
701
|
+
let(:mappings) do
|
702
|
+
{
|
703
|
+
"first_name" => "givenName",
|
704
|
+
"last_name" => "sn",
|
705
|
+
"email" => "mail",
|
706
|
+
"manager" => "manager_dn"
|
707
|
+
}
|
708
|
+
end
|
709
|
+
let(:group_membership_mappings) do
|
710
|
+
{
|
711
|
+
"filter" => "(objectClass=groupOfUniqueNames)",
|
712
|
+
"unique_identifier" => "gid"
|
713
|
+
}
|
714
|
+
end
|
715
|
+
before do
|
716
|
+
ldap.should_receive(:search).once.ordered.with(
|
717
|
+
:return_result => false,
|
718
|
+
:filter => "(objectClass=groupOfUniqueNames)",
|
719
|
+
:base => "dc=example,dc=com",
|
720
|
+
:attributes => ["gid"]).and_yield(group)
|
721
|
+
|
722
|
+
ldap.should_receive(:search).once.ordered.with(
|
723
|
+
:return_result => false,
|
724
|
+
:filter => "(mail=*)",
|
725
|
+
:base => "dc=example,dc=com",
|
726
|
+
:attributes => ["mail"]).and_yield(manager)
|
727
|
+
|
728
|
+
filter1 = Net::LDAP::Filter.construct('(&(mail=*)(mail=user1@example.com))')
|
729
|
+
ldap.should_receive(:search).once.ordered
|
730
|
+
.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'manager_dn', 'isMemberOf'], :filter => filter1))
|
731
|
+
.and_yield(user1)
|
732
|
+
|
733
|
+
filter2 = Net::LDAP::Filter.construct('(&(mail=*)(mail=user2@example.com))')
|
734
|
+
ldap.should_receive(:search).once.ordered
|
735
|
+
.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'manager_dn', 'isMemberOf'], :filter => filter2))
|
736
|
+
.and_yield(user2)
|
737
|
+
end
|
738
|
+
it "caches managers and groups" do
|
739
|
+
connector.fetch_user_hash('user1@example.com', :identifying_field => 'email').should == {
|
740
|
+
'account_type' => 'member',
|
741
|
+
'contact_info' => {
|
742
|
+
'email' => 'user1@example.com'
|
743
|
+
},
|
744
|
+
'custom_fields' => [{ 'id' => 'manager_email', 'label' => 'manager_email', 'value' => nil }],
|
745
|
+
'first_name' => 'first name 1',
|
746
|
+
'last_name' => 'last name 1',
|
747
|
+
'groups' => [],
|
748
|
+
'roles' => []
|
749
|
+
}
|
750
|
+
|
751
|
+
connector.fetch_user_hash('user2@example.com', :identifying_field => 'email').should == {
|
752
|
+
'account_type' => 'member',
|
753
|
+
'contact_info' => {
|
754
|
+
'email' => 'user2@example.com'
|
755
|
+
},
|
756
|
+
'custom_fields' => [{ 'id' => 'manager_email', 'label' => 'manager_email', 'value' => nil }],
|
757
|
+
'first_name' => 'first name 2',
|
758
|
+
'last_name' => 'last name 2',
|
759
|
+
'groups' => ['sales_group_id'],
|
760
|
+
'roles' => []
|
761
|
+
}
|
762
|
+
end
|
763
|
+
end
|
654
764
|
end
|
655
765
|
|
656
766
|
describe "#grab" do
|
@@ -661,7 +771,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
661
771
|
"email" => "mail"
|
662
772
|
}
|
663
773
|
end
|
664
|
-
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config
|
774
|
+
let(:connector) { Socialcast::CommandLine::LDAPConnector.new('connection_1', ldap_config) }
|
665
775
|
let(:entry) do
|
666
776
|
Net::LDAP::Entry.new("cn=sean,dc=example,dc=com").tap do |e|
|
667
777
|
e[:mail] = 'sean@example.com'
|
@@ -670,12 +780,12 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
670
780
|
let(:ldap_instance) { double(Net::LDAP, :encryption => nil, :auth => nil) }
|
671
781
|
context "passed hash for attribute" do
|
672
782
|
it "returns a string that used defined string template" do
|
673
|
-
connector.grab
|
783
|
+
connector.send(:grab, entry, { "value" => "123%{mail}", "mail" => "mail" }).should == "123sean@example.com"
|
674
784
|
end
|
675
785
|
end
|
676
786
|
context "passed string for attribute" do
|
677
787
|
it "returns exact string stored in entry" do
|
678
|
-
connector.grab
|
788
|
+
connector.send(:grab, entry, "mail").should == "sean@example.com"
|
679
789
|
end
|
680
790
|
end
|
681
791
|
context "passed string that can be constantized and the resulting Class responds to run" do
|
@@ -687,7 +797,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
687
797
|
end
|
688
798
|
end
|
689
799
|
end
|
690
|
-
connector.grab
|
800
|
+
connector.send(:grab, entry, "Socialcast::CommandLine::FakeAttributeMap").should == "sebn@exbmple.com"
|
691
801
|
end
|
692
802
|
end
|
693
803
|
context "passed string that must be classified and the resulting Class responds to run" do
|
@@ -699,7 +809,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
699
809
|
end
|
700
810
|
end
|
701
811
|
end
|
702
|
-
connector.grab
|
812
|
+
connector.send(:grab, entry, "socialcast/command_line/fake_attribute_map").should == "sebn@exbmple.com"
|
703
813
|
end
|
704
814
|
end
|
705
815
|
context "attribute passed has a collision between string and Class" do
|
@@ -714,7 +824,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
714
824
|
Object.send(:remove_const, :Mail)
|
715
825
|
end
|
716
826
|
it "returns the result of the Class run method" do
|
717
|
-
connector.grab
|
827
|
+
connector.send(:grab, entry, "mail").should == "sebn@exbmple.com"
|
718
828
|
end
|
719
829
|
end
|
720
830
|
context "attribute passed constantizes to a module instead of a class" do
|
@@ -724,7 +834,7 @@ describe Socialcast::CommandLine::LDAPConnector do
|
|
724
834
|
return "#{entry[:mail].first.gsub(/a/,'b')}"
|
725
835
|
end
|
726
836
|
end
|
727
|
-
connector.grab
|
837
|
+
connector.send(:grab, entry, "FakeAttributeMap").should == "sebn@exbmple.com"
|
728
838
|
end
|
729
839
|
end
|
730
840
|
end
|
@@ -12,7 +12,7 @@ describe Socialcast::CommandLine::ProvisionPhoto do
|
|
12
12
|
|
13
13
|
let(:ldap) do
|
14
14
|
ldap_instance = double(Net::LDAP, :auth => nil, :encryption => nil)
|
15
|
-
ldap_instance.should_receive(:open).and_yield
|
15
|
+
ldap_instance.should_receive(:open).and_yield
|
16
16
|
Net::LDAP.should_receive(:new).and_return(ldap_instance)
|
17
17
|
ldap_instance
|
18
18
|
end
|
@@ -143,13 +143,13 @@ describe Socialcast::CommandLine::ProvisionPhoto do
|
|
143
143
|
stub_const("Socialcast::CommandLine::ProvisionPhoto::MAX_BATCH_SIZE", 2)
|
144
144
|
|
145
145
|
ldap_instance1 = double(Net::LDAP, :encryption => nil, :auth => nil)
|
146
|
-
ldap_instance1.should_receive(:open).and_yield
|
146
|
+
ldap_instance1.should_receive(:open).and_yield
|
147
147
|
Net::LDAP.should_receive(:new).once.ordered.and_return(ldap_instance1)
|
148
148
|
entry1 = create_entry 'user', :mailCon => 'user@example.com', :photoCon => binary_photo_data
|
149
149
|
ldap_instance1.should_receive(:search).once.with(hash_including(:attributes => ['mailCon', 'photoCon'])).and_yield(entry1)
|
150
150
|
|
151
151
|
ldap_instance2 = double(Net::LDAP, :encryption => nil, :auth => nil)
|
152
|
-
ldap_instance2.should_receive(:open).and_yield
|
152
|
+
ldap_instance2.should_receive(:open).and_yield
|
153
153
|
Net::LDAP.should_receive(:new).once.ordered.and_return(ldap_instance2)
|
154
154
|
entry2 = create_entry 'user', :mailCon2 => 'user2@example.com', :photoCon2 => binary_photo_data
|
155
155
|
ldap_instance2.should_receive(:search).once.with(hash_including(:attributes => ['mailCon2', 'photoCon2'])).and_yield(entry2)
|
@@ -19,7 +19,7 @@ describe Socialcast::CommandLine::ProvisionUser do
|
|
19
19
|
|
20
20
|
let(:ldap) do
|
21
21
|
ldap_instance = double(Net::LDAP, :auth => nil, :encryption => nil)
|
22
|
-
ldap_instance.should_receive(:open).and_yield
|
22
|
+
ldap_instance.should_receive(:open).and_yield
|
23
23
|
Net::LDAP.should_receive(:new).and_return(ldap_instance)
|
24
24
|
ldap_instance
|
25
25
|
end
|
@@ -117,13 +117,13 @@ describe Socialcast::CommandLine::ProvisionUser do
|
|
117
117
|
provision_instance = Socialcast::CommandLine::ProvisionUser.new(ldap_multiple_connection_mapping_config, {})
|
118
118
|
|
119
119
|
ldap_instance1 = double(Net::LDAP, :encryption => nil, :auth => nil)
|
120
|
-
ldap_instance1.should_receive(:open).and_yield
|
120
|
+
ldap_instance1.should_receive(:open).and_yield
|
121
121
|
Net::LDAP.should_receive(:new).once.ordered.and_return(ldap_instance1)
|
122
122
|
entry1 = create_entry 'user', :mailCon => 'user@example.com', :givenName => 'first name', :sn => 'last name'
|
123
123
|
ldap_instance1.should_receive(:search).once.with(hash_including(:attributes => ['mailCon', 'isMemberOf'])).and_yield(entry1)
|
124
124
|
|
125
125
|
ldap_instance2 = double(Net::LDAP, :encryption => nil, :auth => nil)
|
126
|
-
ldap_instance2.should_receive(:open).and_yield
|
126
|
+
ldap_instance2.should_receive(:open).and_yield
|
127
127
|
Net::LDAP.should_receive(:new).once.ordered.and_return(ldap_instance2)
|
128
128
|
entry2 = create_entry 'user', :mailCon2 => 'user2@example.com', :firstName => 'first name2', :sn => 'last name2'
|
129
129
|
ldap_instance2.should_receive(:search).once.with(hash_including(:attributes => ['mailCon2', 'firstName', 'isMemberOf'])).and_yield(entry2)
|
@@ -177,7 +177,7 @@ describe Socialcast::CommandLine::ProvisionUser do
|
|
177
177
|
provision_instance = Socialcast::CommandLine::ProvisionUser.new(ldap_with_manager_attribute_config, {})
|
178
178
|
|
179
179
|
ldap_instance = double(Net::LDAP, :encryption => nil, :auth => nil)
|
180
|
-
ldap_instance.should_receive(:open).and_yield
|
180
|
+
ldap_instance.should_receive(:open).and_yield
|
181
181
|
Net::LDAP.should_receive(:new).once.and_return(ldap_instance)
|
182
182
|
|
183
183
|
user_entry = create_entry 'user', :mail => 'user@example.com', :ldap_manager => 'cn=theboss,dc=example,dc=com'
|
@@ -375,13 +375,13 @@ describe Socialcast::CommandLine::ProvisionUser do
|
|
375
375
|
provision_instance = Socialcast::CommandLine::ProvisionUser.new(ldap_multiple_connection_permission_mapping_config, {})
|
376
376
|
|
377
377
|
ldap_instance1 = double(Net::LDAP, :encryption => nil, :auth => nil)
|
378
|
-
ldap_instance1.should_receive(:open).and_yield
|
378
|
+
ldap_instance1.should_receive(:open).and_yield
|
379
379
|
Net::LDAP.should_receive(:new).once.ordered.and_return(ldap_instance1)
|
380
380
|
entry1 = create_entry 'user', :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"]
|
381
381
|
ldap_instance1.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'memberOf'])).and_yield(entry1)
|
382
382
|
|
383
383
|
ldap_instance2 = double(Net::LDAP, :encryption => nil, :auth => nil)
|
384
|
-
ldap_instance2.should_receive(:open).and_yield
|
384
|
+
ldap_instance2.should_receive(:open).and_yield
|
385
385
|
Net::LDAP.should_receive(:new).once.ordered.and_return(ldap_instance2)
|
386
386
|
entry2 = create_entry 'user', :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"]
|
387
387
|
ldap_instance2.should_receive(:search).once.with(hash_including(:attributes => ['givenName', 'sn', 'mail', 'member'])).and_yield(entry2)
|
@@ -411,7 +411,7 @@ describe Socialcast::CommandLine::ProvisionUser do
|
|
411
411
|
root_entry = create_entry('domain', :namingcontexts => ['dc=foo,dc=com', 'dc=bar,dc=com'])
|
412
412
|
ldap_instance = double(Net::LDAP, :encryption => nil, :auth => nil)
|
413
413
|
ldap_instance.should_receive(:search_root_dse).once.and_return(root_entry)
|
414
|
-
ldap_instance.should_receive(:open).and_yield
|
414
|
+
ldap_instance.should_receive(:open).and_yield
|
415
415
|
Net::LDAP.should_receive(:new).once.and_return(ldap_instance)
|
416
416
|
|
417
417
|
user_entry = create_entry 'user', :mail => 'user@example.com', :givenName => 'first name', :sn => 'last name'
|
@@ -474,14 +474,14 @@ describe Socialcast::CommandLine::ProvisionUser do
|
|
474
474
|
let(:entry) { create_entry 'user', :mailCon2 => 'user@example.com', :firstName => 'first name' }
|
475
475
|
before do
|
476
476
|
ldap_instance1 = double(Net::LDAP, :auth => nil)
|
477
|
-
ldap_instance1.should_receive(:open).and_yield
|
477
|
+
ldap_instance1.should_receive(:open).and_yield
|
478
478
|
Net::LDAP.should_receive(:new).once.ordered.and_return(ldap_instance1)
|
479
479
|
filter1 = Net::LDAP::Filter.construct('(&(mail=*)(mailCon=user@example.com))')
|
480
480
|
ldap_instance1.should_receive(:search).once.ordered
|
481
481
|
.with(hash_including(:attributes => ['mailCon', 'isMemberOf'], :filter => filter1))
|
482
482
|
|
483
483
|
ldap_instance2 = double(Net::LDAP, :auth => nil)
|
484
|
-
ldap_instance2.should_receive(:open).and_yield
|
484
|
+
ldap_instance2.should_receive(:open).and_yield
|
485
485
|
Net::LDAP.should_receive(:new).once.ordered.and_return(ldap_instance2)
|
486
486
|
filter2 = Net::LDAP::Filter.construct('(&(mail=*)(mailCon2=user@example.com))')
|
487
487
|
ldap_instance2.should_receive(:search).once.ordered
|
@@ -505,14 +505,14 @@ describe Socialcast::CommandLine::ProvisionUser do
|
|
505
505
|
let(:provision_instance) { Socialcast::CommandLine::ProvisionUser.new(ldap_multiple_connection_mapping_config, {}) }
|
506
506
|
before do
|
507
507
|
ldap_instance1 = double(Net::LDAP, :auth => nil)
|
508
|
-
ldap_instance1.should_receive(:open).and_yield
|
508
|
+
ldap_instance1.should_receive(:open).and_yield
|
509
509
|
Net::LDAP.should_receive(:new).once.ordered.and_return(ldap_instance1)
|
510
510
|
filter1 = Net::LDAP::Filter.construct('(&(mail=*)(mailCon=user@example.com))')
|
511
511
|
ldap_instance1.should_receive(:search)
|
512
512
|
.with(hash_including(:attributes => ['mailCon', 'isMemberOf'], :filter => filter1))
|
513
513
|
|
514
514
|
ldap_instance2 = double(Net::LDAP, :auth => nil)
|
515
|
-
ldap_instance2.should_receive(:open).and_yield
|
515
|
+
ldap_instance2.should_receive(:open).and_yield
|
516
516
|
Net::LDAP.should_receive(:new).once.ordered.and_return(ldap_instance2)
|
517
517
|
filter2 = Net::LDAP::Filter.construct('(&(mail=*)(mailCon2=user@example.com))')
|
518
518
|
ldap_instance2.should_receive(:search).once.ordered
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: socialcast
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Sonnek
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2014-06-
|
13
|
+
date: 2014-06-19 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rest-client
|