socialcast 1.3.11 → 1.3.12
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.
- 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
|