vines 0.4.3 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +1 -1
- data/lib/vines/storage.rb +28 -33
- data/lib/vines/storage/ldap.rb +5 -4
- data/lib/vines/storage/sql.rb +2 -3
- data/lib/vines/version.rb +1 -1
- data/test/storage/ldap_test.rb +147 -145
- data/test/storage/mock_redis.rb +2 -3
- data/test/storage_test.rb +39 -49
- metadata +35 -35
data/Rakefile
CHANGED
@@ -41,7 +41,7 @@ is mandatory on all client and server connections."
|
|
41
41
|
s.add_dependency "http_parser.rb", "~> 0.5.3"
|
42
42
|
s.add_dependency "mongo", "~> 1.5.2"
|
43
43
|
s.add_dependency "bson_ext", "~> 1.5.2"
|
44
|
-
s.add_dependency "net-ldap", "~> 0.
|
44
|
+
s.add_dependency "net-ldap", "~> 0.3.1"
|
45
45
|
s.add_dependency "nokogiri", "~> 1.4.7"
|
46
46
|
|
47
47
|
s.add_development_dependency "minitest", "~> 2.12.1"
|
data/lib/vines/storage.rb
CHANGED
@@ -35,18 +35,10 @@ module Vines
|
|
35
35
|
# enabled library like em-http-request or em-redis) don't need any special
|
36
36
|
# consideration and must not use this method.
|
37
37
|
def self.defer(method)
|
38
|
-
old =
|
39
|
-
alias_method old, method
|
38
|
+
old = instance_method(method)
|
40
39
|
define_method method do |*args|
|
41
40
|
fiber = Fiber.current
|
42
|
-
op =
|
43
|
-
begin
|
44
|
-
method(old).call(*args)
|
45
|
-
rescue => e
|
46
|
-
log.error("Thread pool operation failed: #{e.message}")
|
47
|
-
nil
|
48
|
-
end
|
49
|
-
end
|
41
|
+
op = operation { old.bind(self).call(*args) }
|
50
42
|
cb = proc {|result| fiber.resume(result) }
|
51
43
|
EM.defer(op, cb)
|
52
44
|
Fiber.yield
|
@@ -64,10 +56,9 @@ module Vines
|
|
64
56
|
# end
|
65
57
|
# wrap_ldap :authenticate
|
66
58
|
def self.wrap_ldap(method)
|
67
|
-
old =
|
68
|
-
alias_method old, method
|
59
|
+
old = instance_method(method)
|
69
60
|
define_method method do |*args|
|
70
|
-
ldap? ? authenticate_with_ldap(*args) :
|
61
|
+
ldap? ? authenticate_with_ldap(*args) : old.bind(self).call(*args)
|
71
62
|
end
|
72
63
|
end
|
73
64
|
|
@@ -89,24 +80,23 @@ module Vines
|
|
89
80
|
# user = storage.find_user('alice@wonderland.lit')
|
90
81
|
# puts user.nil?
|
91
82
|
def self.fiber(method)
|
92
|
-
old =
|
93
|
-
alias_method old, method
|
83
|
+
old = instance_method(method)
|
94
84
|
define_method method do |*args|
|
95
85
|
fiber, yielding = Fiber.current, true
|
96
|
-
|
86
|
+
old.bind(self).call(*args) do |user|
|
97
87
|
fiber.resume(user) rescue yielding = false
|
98
88
|
end
|
99
89
|
Fiber.yield if yielding
|
100
90
|
end
|
101
91
|
end
|
102
92
|
|
103
|
-
# Return true if users are authenticated against an LDAP directory.
|
93
|
+
# Return +true+ if users are authenticated against an LDAP directory.
|
104
94
|
def ldap?
|
105
95
|
!!ldap
|
106
96
|
end
|
107
97
|
|
108
|
-
# Validate the username and password pair and return a Vines::User object
|
109
|
-
# on success. Return nil on failure.
|
98
|
+
# Validate the username and password pair and return a +Vines::User+ object
|
99
|
+
# on success. Return +nil+ on failure.
|
110
100
|
#
|
111
101
|
# For example:
|
112
102
|
# user = storage.authenticate('alice@wonderland.lit', 'secr3t')
|
@@ -122,7 +112,7 @@ module Vines
|
|
122
112
|
end
|
123
113
|
wrap_ldap :authenticate
|
124
114
|
|
125
|
-
# Return the Vines::User associated with the JID. Return nil if the user
|
115
|
+
# Return the +Vines::User+ associated with the JID. Return +nil+ if the user
|
126
116
|
# could not be found. JID may be +nil+, a +String+, or a +Vines::JID+
|
127
117
|
# object. It may be a bare JID or a full JID. Implementations of this method
|
128
118
|
# must convert the JID to a bare JID before searching for the user in the
|
@@ -134,7 +124,7 @@ module Vines
|
|
134
124
|
raise 'subclass must implement'
|
135
125
|
end
|
136
126
|
|
137
|
-
# Persist the Vines::User object to the database and return when the save
|
127
|
+
# Persist the +Vines::User+ object to the database and return when the save
|
138
128
|
# is complete.
|
139
129
|
#
|
140
130
|
# alice = Vines::User.new(:jid => 'alice@wonderland.lit')
|
@@ -206,28 +196,33 @@ module Vines
|
|
206
196
|
args.flatten.any? {|arg| (arg || '').strip.empty? }
|
207
197
|
end
|
208
198
|
|
209
|
-
# Return a
|
210
|
-
#
|
211
|
-
|
212
|
-
|
213
|
-
def authenticate_with_ldap(username, password, &block)
|
214
|
-
if empty?(username, password)
|
215
|
-
block.call; return
|
216
|
-
end
|
217
|
-
|
218
|
-
op = proc do
|
199
|
+
# Return a +proc+ suitable for running on the +EM.defer+ thread pool that traps
|
200
|
+
# and logs any errors thrown by the provided block.
|
201
|
+
def operation
|
202
|
+
proc do
|
219
203
|
begin
|
220
|
-
|
204
|
+
yield
|
221
205
|
rescue => e
|
222
|
-
log.error("
|
206
|
+
log.error("Thread pool operation failed: #{e.message}")
|
223
207
|
nil
|
224
208
|
end
|
225
209
|
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# Return a +Vines::User+ object if we are able to bind to the LDAP server
|
213
|
+
# using the username and password. Return +nil+ if authentication failed. If
|
214
|
+
# authentication succeeds, but the user is not yet stored in our database,
|
215
|
+
# save the user to the database.
|
216
|
+
def authenticate_with_ldap(username, password, &block)
|
217
|
+
op = operation { ldap.authenticate(username, password) }
|
226
218
|
cb = proc {|user| save_ldap_user(user, &block) }
|
227
219
|
EM.defer(op, cb)
|
228
220
|
end
|
229
221
|
fiber :authenticate_with_ldap
|
230
222
|
|
223
|
+
# Save missing users to the storage database after they're authenticated with
|
224
|
+
# LDAP. This allows admins to define users once in LDAP and have them sync
|
225
|
+
# to the chat database the first time they successfully sign in.
|
231
226
|
def save_ldap_user(user, &block)
|
232
227
|
Fiber.new do
|
233
228
|
if user.nil?
|
data/lib/vines/storage/ldap.rb
CHANGED
@@ -17,7 +17,7 @@ module Vines
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def initialize(host='localhost', port=636, &block)
|
20
|
-
@config = {:
|
20
|
+
@config = {host: host, port: port}
|
21
21
|
instance_eval(&block)
|
22
22
|
@@required.each {|key| raise "Must provide #{key}" if @config[key].nil? }
|
23
23
|
end
|
@@ -26,17 +26,18 @@ module Vines
|
|
26
26
|
# those credentials. If the bind succeeds, the user's attributes are
|
27
27
|
# retrieved.
|
28
28
|
def authenticate(username, password)
|
29
|
+
username = JID.new(username).to_s rescue nil
|
29
30
|
return if [username, password].any? {|arg| (arg || '').strip.empty? }
|
30
31
|
|
31
32
|
ldap = connect(@config[:dn], @config[:password])
|
32
33
|
entries = ldap.search(
|
33
|
-
:
|
34
|
-
:
|
34
|
+
attributes: [@config[:name_attr], 'mail'],
|
35
|
+
filter: filter(username))
|
35
36
|
return unless entries && entries.size == 1
|
36
37
|
|
37
38
|
user = if connect(entries.first.dn, password).bind
|
38
39
|
name = entries.first[@config[:name_attr]].first
|
39
|
-
User.new(:
|
40
|
+
User.new(jid: username, name: name.to_s, roster: [])
|
40
41
|
end
|
41
42
|
user
|
42
43
|
end
|
data/lib/vines/storage/sql.rb
CHANGED
@@ -23,11 +23,10 @@ module Vines
|
|
23
23
|
# ActiveRecord uses blocking IO.
|
24
24
|
def self.with_connection(method, args={})
|
25
25
|
deferrable = args.key?(:defer) ? args[:defer] : true
|
26
|
-
old =
|
27
|
-
alias_method old, method
|
26
|
+
old = instance_method(method)
|
28
27
|
define_method method do |*args|
|
29
28
|
ActiveRecord::Base.connection_pool.with_connection do
|
30
|
-
|
29
|
+
old.bind(self).call(*args)
|
31
30
|
end
|
32
31
|
end
|
33
32
|
defer(method) if deferrable
|
data/lib/vines/version.rb
CHANGED
data/test/storage/ldap_test.rb
CHANGED
@@ -3,20 +3,31 @@
|
|
3
3
|
require 'vines'
|
4
4
|
require 'minitest/autorun'
|
5
5
|
|
6
|
-
|
6
|
+
describe Vines::Storage::Ldap do
|
7
7
|
ALICE_DN = 'uid=alice@wondlerand.lit,ou=People,dc=wonderland,dc=lit'
|
8
8
|
CONTEXT = {}
|
9
9
|
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
def teardown
|
10
|
+
after do
|
14
11
|
CONTEXT.clear
|
15
12
|
end
|
16
13
|
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
describe '#initialize' do
|
15
|
+
it 'raises with missing host and port' do
|
16
|
+
assert_raises(RuntimeError) do
|
17
|
+
Vines::Storage::Ldap.new(nil, nil) do
|
18
|
+
tls true
|
19
|
+
dn 'cn=Directory Manager'
|
20
|
+
password 'secr3t'
|
21
|
+
basedn 'dc=wonderland,dc=lit'
|
22
|
+
object_class 'person'
|
23
|
+
user_attr 'uid'
|
24
|
+
name_attr 'cn'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'does not raise when using default host and port' do
|
30
|
+
Vines::Storage::Ldap.new do
|
20
31
|
tls true
|
21
32
|
dn 'cn=Directory Manager'
|
22
33
|
password 'secr3t'
|
@@ -26,162 +37,153 @@ class LdapTest < MiniTest::Unit::TestCase
|
|
26
37
|
name_attr 'cn'
|
27
38
|
end
|
28
39
|
end
|
29
|
-
end
|
30
40
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
41
|
+
it 'does not raise when given a host and port' do
|
42
|
+
Vines::Storage::Ldap.new('0.0.0.1', 42) do
|
43
|
+
tls true
|
44
|
+
dn 'cn=Directory Manager'
|
45
|
+
password 'secr3t'
|
46
|
+
basedn 'dc=wonderland,dc=lit'
|
47
|
+
object_class 'person'
|
48
|
+
user_attr 'uid'
|
49
|
+
name_attr 'cn'
|
50
|
+
end
|
40
51
|
end
|
41
|
-
end
|
42
52
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
password 'secr3t'
|
48
|
-
basedn 'dc=wonderland,dc=lit'
|
49
|
-
object_class 'person'
|
50
|
-
user_attr 'uid'
|
51
|
-
name_attr 'cn'
|
53
|
+
it 'raises when given no parameters' do
|
54
|
+
assert_raises(RuntimeError) do
|
55
|
+
Vines::Storage::Ldap.new {}
|
56
|
+
end
|
52
57
|
end
|
53
|
-
end
|
54
58
|
|
55
|
-
|
56
|
-
|
57
|
-
|
59
|
+
it 'raises when given blank parameters' do
|
60
|
+
assert_raises(RuntimeError) do
|
61
|
+
Vines::Storage::Ldap.new do
|
62
|
+
tls
|
63
|
+
dn
|
64
|
+
password
|
65
|
+
basedn
|
66
|
+
object_class
|
67
|
+
user_attr
|
68
|
+
name_attr
|
69
|
+
end
|
70
|
+
end
|
58
71
|
end
|
59
|
-
end
|
60
72
|
|
61
|
-
|
62
|
-
assert_raises(RuntimeError) do
|
73
|
+
it 'handles boolean false values without raising' do
|
63
74
|
Vines::Storage::Ldap.new do
|
64
|
-
tls
|
65
|
-
dn
|
66
|
-
password
|
67
|
-
basedn
|
68
|
-
object_class
|
69
|
-
user_attr
|
70
|
-
name_attr
|
75
|
+
tls false
|
76
|
+
dn 'cn=Directory Manager'
|
77
|
+
password 'secr3t'
|
78
|
+
basedn 'dc=wonderland,dc=lit'
|
79
|
+
object_class 'person'
|
80
|
+
user_attr 'uid'
|
81
|
+
name_attr 'cn'
|
71
82
|
end
|
72
83
|
end
|
73
84
|
end
|
74
85
|
|
75
|
-
#
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
user_attr 'uid'
|
84
|
-
name_attr 'cn'
|
86
|
+
describe '#authenticate' do
|
87
|
+
it 'fails with invalid credentials' do
|
88
|
+
ldap = connect
|
89
|
+
assert_nil ldap.authenticate(nil, nil)
|
90
|
+
assert_nil ldap.authenticate('', '')
|
91
|
+
assert_nil ldap.authenticate('alice@wonderland.lit', ' ')
|
92
|
+
assert_nil ldap.authenticate('bogus"jid@wonderland.lit', 'password')
|
93
|
+
assert_nil ldap.authenticate(Vines::JID.new('alice@wonderland.lit'), '')
|
85
94
|
end
|
86
|
-
end
|
87
95
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
mock = CONTEXT[:mock_ldap]
|
110
|
-
mock.expect(:search, [], [{:attributes => ['cn', 'mail'], :filter => clas & uid}])
|
96
|
+
it 'fails when user not found' do
|
97
|
+
CONTEXT.merge!({
|
98
|
+
:mock_ldap => MiniTest::Mock.new,
|
99
|
+
:connect_calls => 0
|
100
|
+
})
|
101
|
+
ldap = connect
|
102
|
+
def ldap.connect(dn, password)
|
103
|
+
CONTEXT[:connect_calls] += 1
|
104
|
+
raise unless 'cn=Directory Manager' == dn
|
105
|
+
raise unless 'secr3t' == password
|
106
|
+
|
107
|
+
clas = Net::LDAP::Filter.eq('objectClass', 'person')
|
108
|
+
uid = Net::LDAP::Filter.eq('uid', 'alice@wonderland.lit')
|
109
|
+
|
110
|
+
mock = CONTEXT[:mock_ldap]
|
111
|
+
mock.expect(:search, [], [{:attributes => ['cn', 'mail'], :filter => clas & uid}])
|
112
|
+
end
|
113
|
+
assert_nil ldap.authenticate('alice@wonderland.lit', 'passw0rd')
|
114
|
+
assert CONTEXT[:mock_ldap]
|
115
|
+
assert_equal 1, CONTEXT[:connect_calls]
|
111
116
|
end
|
112
|
-
assert_nil ldap.authenticate('alice@wonderland.lit', 'passw0rd')
|
113
|
-
assert CONTEXT[:mock_ldap]
|
114
|
-
assert_equal 1, CONTEXT[:connect_calls]
|
115
|
-
end
|
116
117
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
118
|
+
it 'fails when user cannot bind' do
|
119
|
+
CONTEXT.merge!({
|
120
|
+
:credentials => [
|
121
|
+
{:dn => 'cn=Directory Manager', :password => 'secr3t'},
|
122
|
+
{:dn => ALICE_DN, :password => 'passw0rd'}
|
123
|
+
],
|
124
|
+
:mock_ldap => MiniTest::Mock.new,
|
125
|
+
:mock_entry => MiniTest::Mock.new,
|
126
|
+
:connect_calls => 0
|
127
|
+
})
|
128
|
+
ldap = connect
|
129
|
+
def ldap.connect(dn, password)
|
130
|
+
credentials = CONTEXT[:credentials][CONTEXT[:connect_calls]]
|
131
|
+
CONTEXT[:connect_calls] += 1
|
132
|
+
raise unless credentials[:dn] == dn && credentials[:password] == password
|
133
|
+
|
134
|
+
clas = Net::LDAP::Filter.eq('objectClass', 'person')
|
135
|
+
uid = Net::LDAP::Filter.eq('uid', 'alice@wonderland.lit')
|
136
|
+
|
137
|
+
entry = CONTEXT[:mock_entry]
|
138
|
+
entry.expect(:dn, ALICE_DN)
|
139
|
+
|
140
|
+
mock = CONTEXT[:mock_ldap]
|
141
|
+
mock.expect(:search, [entry], [{:attributes => ['cn', 'mail'], :filter => clas & uid}])
|
142
|
+
mock.expect(:bind, false)
|
143
|
+
end
|
144
|
+
assert_nil ldap.authenticate('alice@wonderland.lit', 'passw0rd')
|
145
|
+
assert_equal 2, CONTEXT[:connect_calls]
|
146
|
+
assert CONTEXT[:mock_entry].verify
|
147
|
+
assert CONTEXT[:mock_ldap].verify
|
142
148
|
end
|
143
|
-
assert_nil ldap.authenticate('alice@wonderland.lit', 'passw0rd')
|
144
|
-
assert_equal 2, CONTEXT[:connect_calls]
|
145
|
-
assert CONTEXT[:mock_entry].verify
|
146
|
-
assert CONTEXT[:mock_ldap].verify
|
147
|
-
end
|
148
149
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
150
|
+
it 'authenticates successfully with proper credentials' do
|
151
|
+
CONTEXT.merge!({
|
152
|
+
:credentials => [
|
153
|
+
{:dn => 'cn=Directory Manager', :password => 'secr3t'},
|
154
|
+
{:dn => ALICE_DN, :password => 'passw0rd'}
|
155
|
+
],
|
156
|
+
:mock_ldap => MiniTest::Mock.new,
|
157
|
+
:mock_entry => MiniTest::Mock.new,
|
158
|
+
:connect_calls => 0
|
159
|
+
})
|
160
|
+
ldap = connect
|
161
|
+
def ldap.connect(dn, password)
|
162
|
+
credentials = CONTEXT[:credentials][CONTEXT[:connect_calls]]
|
163
|
+
CONTEXT[:connect_calls] += 1
|
164
|
+
raise unless credentials[:dn] == dn && credentials[:password] == password
|
165
|
+
|
166
|
+
clas = Net::LDAP::Filter.eq('objectClass', 'person')
|
167
|
+
uid = Net::LDAP::Filter.eq('uid', 'alice@wonderland.lit')
|
168
|
+
|
169
|
+
entry = CONTEXT[:mock_entry]
|
170
|
+
entry.expect(:dn, ALICE_DN)
|
171
|
+
entry.expect(:[], ['Alice Liddell'], ['cn'])
|
172
|
+
|
173
|
+
mock = CONTEXT[:mock_ldap]
|
174
|
+
mock.expect(:search, [entry], [{:attributes => ['cn', 'mail'], :filter => clas & uid}])
|
175
|
+
mock.expect(:bind, true)
|
176
|
+
end
|
177
|
+
user = ldap.authenticate('alice@wonderland.lit', 'passw0rd')
|
178
|
+
refute_nil user
|
179
|
+
assert_equal 'alice@wonderland.lit', user.jid.to_s
|
180
|
+
assert_equal 'Alice Liddell', user.name
|
181
|
+
assert_equal [], user.roster
|
182
|
+
|
183
|
+
assert_equal 2, CONTEXT[:connect_calls]
|
184
|
+
assert CONTEXT[:mock_entry].verify
|
185
|
+
assert CONTEXT[:mock_ldap].verify
|
175
186
|
end
|
176
|
-
user = ldap.authenticate('alice@wonderland.lit', 'passw0rd')
|
177
|
-
refute_nil user
|
178
|
-
assert_equal 'alice@wonderland.lit', user.jid.to_s
|
179
|
-
assert_equal 'Alice Liddell', user.name
|
180
|
-
assert_equal [], user.roster
|
181
|
-
|
182
|
-
assert_equal 2, CONTEXT[:connect_calls]
|
183
|
-
assert CONTEXT[:mock_entry].verify
|
184
|
-
assert CONTEXT[:mock_ldap].verify
|
185
187
|
end
|
186
188
|
|
187
189
|
private
|
data/test/storage/mock_redis.rb
CHANGED
@@ -6,10 +6,9 @@ class MockRedis
|
|
6
6
|
|
7
7
|
# Mimic em-hiredis behavior.
|
8
8
|
def self.defer(method)
|
9
|
-
old =
|
10
|
-
alias_method old, method
|
9
|
+
old = instance_method(method)
|
11
10
|
define_method method do |*args, &block|
|
12
|
-
result =
|
11
|
+
result = old.bind(self).call(*args)
|
13
12
|
deferred = EM::DefaultDeferrable.new
|
14
13
|
deferred.callback(&block) if block
|
15
14
|
EM.next_tick { deferred.succeed(result) }
|
data/test/storage_test.rb
CHANGED
@@ -4,7 +4,7 @@ require 'storage_tests'
|
|
4
4
|
require 'vines'
|
5
5
|
require 'minitest/autorun'
|
6
6
|
|
7
|
-
|
7
|
+
describe Vines::Storage do
|
8
8
|
ALICE = 'alice@wonderland.lit'.freeze
|
9
9
|
|
10
10
|
class MockLdapStorage < Vines::Storage
|
@@ -39,58 +39,48 @@ class StorageTest < MiniTest::Unit::TestCase
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
42
|
+
describe '#authenticate_with_ldap' do
|
43
|
+
it 'fails when given a bad password' do
|
44
|
+
StorageTests::EMLoop.new do
|
45
|
+
storage = MockLdapStorage.new
|
46
|
+
storage.ldap.user = nil
|
47
|
+
user = storage.authenticate(ALICE, 'bogus')
|
48
|
+
assert_nil user
|
49
|
+
assert_equal 0, storage.authenticate_calls
|
50
|
+
assert_equal 0, storage.find_user_calls
|
51
|
+
assert_equal 0, storage.save_user_calls
|
52
|
+
assert_equal [ALICE, 'bogus'], storage.ldap.auth.first
|
53
|
+
end
|
51
54
|
end
|
52
|
-
end
|
53
55
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
56
|
+
it 'succeeds when user exists in database' do
|
57
|
+
StorageTests::EMLoop.new do
|
58
|
+
alice = Vines::User.new(:jid => ALICE)
|
59
|
+
storage = MockLdapStorage.new(alice)
|
60
|
+
storage.ldap.user = alice
|
61
|
+
user = storage.authenticate(ALICE, 'secr3t')
|
62
|
+
refute_nil user
|
63
|
+
assert_equal ALICE, user.jid.to_s
|
64
|
+
assert_equal 0, storage.authenticate_calls
|
65
|
+
assert_equal 1, storage.find_user_calls
|
66
|
+
assert_equal 0, storage.save_user_calls
|
67
|
+
assert_equal [ALICE, 'secr3t'], storage.ldap.auth.first
|
68
|
+
end
|
64
69
|
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def test_authenticate_with_ldap_user_exists_in_database
|
68
|
-
StorageTests::EMLoop.new do
|
69
|
-
alice = Vines::User.new(:jid => ALICE)
|
70
|
-
storage = MockLdapStorage.new(alice)
|
71
|
-
storage.ldap.user = alice
|
72
|
-
user = storage.authenticate(ALICE, 'secr3t')
|
73
|
-
refute_nil user
|
74
|
-
assert_equal ALICE, user.jid.to_s
|
75
|
-
assert_equal 0, storage.authenticate_calls
|
76
|
-
assert_equal 1, storage.find_user_calls
|
77
|
-
assert_equal 0, storage.save_user_calls
|
78
|
-
assert_equal [ALICE, 'secr3t'], storage.ldap.auth.first
|
79
|
-
end
|
80
|
-
end
|
81
70
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
71
|
+
it 'succeeds and saves user to the database' do
|
72
|
+
StorageTests::EMLoop.new do
|
73
|
+
alice = Vines::User.new(:jid => ALICE)
|
74
|
+
storage = MockLdapStorage.new
|
75
|
+
storage.ldap.user = alice
|
76
|
+
user = storage.authenticate(ALICE, 'secr3t')
|
77
|
+
refute_nil user
|
78
|
+
assert_equal ALICE, user.jid.to_s
|
79
|
+
assert_equal 0, storage.authenticate_calls
|
80
|
+
assert_equal 1, storage.find_user_calls
|
81
|
+
assert_equal 1, storage.save_user_calls
|
82
|
+
assert_equal [ALICE, 'secr3t'], storage.ldap.auth.first
|
83
|
+
end
|
94
84
|
end
|
95
85
|
end
|
96
86
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vines
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-04-
|
12
|
+
date: 2012-04-19 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
16
|
-
requirement: &
|
16
|
+
requirement: &70188360341400 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 3.2.3
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70188360341400
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: bcrypt-ruby
|
27
|
-
requirement: &
|
27
|
+
requirement: &70188360340640 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 3.0.1
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70188360340640
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: em-http-request
|
38
|
-
requirement: &
|
38
|
+
requirement: &70188360339620 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 1.0.2
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70188360339620
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: em-hiredis
|
49
|
-
requirement: &
|
49
|
+
requirement: &70188360334900 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 0.1.1
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70188360334900
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: eventmachine
|
60
|
-
requirement: &
|
60
|
+
requirement: &70188360333880 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 0.12.10
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70188360333880
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: http_parser.rb
|
71
|
-
requirement: &
|
71
|
+
requirement: &70188360332740 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: 0.5.3
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70188360332740
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: mongo
|
82
|
-
requirement: &
|
82
|
+
requirement: &70188360331500 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ~>
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: 1.5.2
|
88
88
|
type: :runtime
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70188360331500
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: bson_ext
|
93
|
-
requirement: &
|
93
|
+
requirement: &70188360330140 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ~>
|
@@ -98,21 +98,21 @@ dependencies:
|
|
98
98
|
version: 1.5.2
|
99
99
|
type: :runtime
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70188360330140
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: net-ldap
|
104
|
-
requirement: &
|
104
|
+
requirement: &70188360329300 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ~>
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version: 0.
|
109
|
+
version: 0.3.1
|
110
110
|
type: :runtime
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *70188360329300
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: nokogiri
|
115
|
-
requirement: &
|
115
|
+
requirement: &70188360328540 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ~>
|
@@ -120,10 +120,10 @@ dependencies:
|
|
120
120
|
version: 1.4.7
|
121
121
|
type: :runtime
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *70188360328540
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
125
|
name: minitest
|
126
|
-
requirement: &
|
126
|
+
requirement: &70188360327640 !ruby/object:Gem::Requirement
|
127
127
|
none: false
|
128
128
|
requirements:
|
129
129
|
- - ~>
|
@@ -131,10 +131,10 @@ dependencies:
|
|
131
131
|
version: 2.12.1
|
132
132
|
type: :development
|
133
133
|
prerelease: false
|
134
|
-
version_requirements: *
|
134
|
+
version_requirements: *70188360327640
|
135
135
|
- !ruby/object:Gem::Dependency
|
136
136
|
name: coffee-script
|
137
|
-
requirement: &
|
137
|
+
requirement: &70188360326740 !ruby/object:Gem::Requirement
|
138
138
|
none: false
|
139
139
|
requirements:
|
140
140
|
- - ~>
|
@@ -142,10 +142,10 @@ dependencies:
|
|
142
142
|
version: 2.2.0
|
143
143
|
type: :development
|
144
144
|
prerelease: false
|
145
|
-
version_requirements: *
|
145
|
+
version_requirements: *70188360326740
|
146
146
|
- !ruby/object:Gem::Dependency
|
147
147
|
name: coffee-script-source
|
148
|
-
requirement: &
|
148
|
+
requirement: &70188360326200 !ruby/object:Gem::Requirement
|
149
149
|
none: false
|
150
150
|
requirements:
|
151
151
|
- - ~>
|
@@ -153,10 +153,10 @@ dependencies:
|
|
153
153
|
version: 1.2.0
|
154
154
|
type: :development
|
155
155
|
prerelease: false
|
156
|
-
version_requirements: *
|
156
|
+
version_requirements: *70188360326200
|
157
157
|
- !ruby/object:Gem::Dependency
|
158
158
|
name: uglifier
|
159
|
-
requirement: &
|
159
|
+
requirement: &70188360325340 !ruby/object:Gem::Requirement
|
160
160
|
none: false
|
161
161
|
requirements:
|
162
162
|
- - ~>
|
@@ -164,10 +164,10 @@ dependencies:
|
|
164
164
|
version: 1.2.4
|
165
165
|
type: :development
|
166
166
|
prerelease: false
|
167
|
-
version_requirements: *
|
167
|
+
version_requirements: *70188360325340
|
168
168
|
- !ruby/object:Gem::Dependency
|
169
169
|
name: rake
|
170
|
-
requirement: &
|
170
|
+
requirement: &70188360324400 !ruby/object:Gem::Requirement
|
171
171
|
none: false
|
172
172
|
requirements:
|
173
173
|
- - ! '>='
|
@@ -175,10 +175,10 @@ dependencies:
|
|
175
175
|
version: '0'
|
176
176
|
type: :development
|
177
177
|
prerelease: false
|
178
|
-
version_requirements: *
|
178
|
+
version_requirements: *70188360324400
|
179
179
|
- !ruby/object:Gem::Dependency
|
180
180
|
name: sqlite3
|
181
|
-
requirement: &
|
181
|
+
requirement: &70188360323440 !ruby/object:Gem::Requirement
|
182
182
|
none: false
|
183
183
|
requirements:
|
184
184
|
- - ! '>='
|
@@ -186,7 +186,7 @@ dependencies:
|
|
186
186
|
version: '0'
|
187
187
|
type: :development
|
188
188
|
prerelease: false
|
189
|
-
version_requirements: *
|
189
|
+
version_requirements: *70188360323440
|
190
190
|
description: ! 'Vines is an XMPP chat server that supports thousands of
|
191
191
|
|
192
192
|
simultaneous connections by using EventMachine for asynchronous IO. User data
|