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 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.2.2"
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"
@@ -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 = "_deferred_#{method}"
39
- alias_method old, method
38
+ old = instance_method(method)
40
39
  define_method method do |*args|
41
40
  fiber = Fiber.current
42
- op = proc do
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 = "_ldap_#{method}"
68
- alias_method old, method
59
+ old = instance_method(method)
69
60
  define_method method do |*args|
70
- ldap? ? authenticate_with_ldap(*args) : method(old).call(*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 = "_fiber_#{method}"
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
- method(old).call(*args) do |user|
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 Vines::User object if we are able to bind to the LDAP server
210
- # using the username and password. Return nil if authentication failed. If
211
- # authentication succeeds, but the user is not yet stored in our database,
212
- # save the user to the database.
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
- ldap.authenticate(username, password)
204
+ yield
221
205
  rescue => e
222
- log.error("LDAP authentication failed: #{e.message}")
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?
@@ -17,7 +17,7 @@ module Vines
17
17
  end
18
18
 
19
19
  def initialize(host='localhost', port=636, &block)
20
- @config = {:host => host, :port => port}
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
- :attributes => [@config[:name_attr], 'mail'],
34
- :filter => filter(username))
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(:jid => username, :name => name.to_s, :roster => [])
40
+ User.new(jid: username, name: name.to_s, roster: [])
40
41
  end
41
42
  user
42
43
  end
@@ -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 = "_with_connection_#{method}"
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
- method(old).call(*args)
29
+ old.bind(self).call(*args)
31
30
  end
32
31
  end
33
32
  defer(method) if deferrable
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  module Vines
4
- VERSION = '0.4.3'
4
+ VERSION = '0.4.4'
5
5
  end
@@ -3,20 +3,31 @@
3
3
  require 'vines'
4
4
  require 'minitest/autorun'
5
5
 
6
- class LdapTest < MiniTest::Unit::TestCase
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
- def setup
11
- end
12
-
13
- def teardown
10
+ after do
14
11
  CONTEXT.clear
15
12
  end
16
13
 
17
- def test_missing_host_and_port
18
- assert_raises(RuntimeError) do
19
- Vines::Storage::Ldap.new(nil, nil) do
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
- def test_default_host_and_port_raises_no_errors
32
- Vines::Storage::Ldap.new do
33
- tls true
34
- dn 'cn=Directory Manager'
35
- password 'secr3t'
36
- basedn 'dc=wonderland,dc=lit'
37
- object_class 'person'
38
- user_attr 'uid'
39
- name_attr 'cn'
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
- def test_configured_host_and_port_raises_no_errors
44
- Vines::Storage::Ldap.new('0.0.0.1', 42) do
45
- tls true
46
- dn 'cn=Directory Manager'
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
- def test_missing_parameters
56
- assert_raises(RuntimeError) do
57
- Vines::Storage::Ldap.new {}
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
- def test_blank_parameters
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
- # Make sure we properly handle boolean false values.
76
- def test_false_tls_raises_no_errors
77
- Vines::Storage::Ldap.new do
78
- tls false
79
- dn 'cn=Directory Manager'
80
- password 'secr3t'
81
- basedn 'dc=wonderland,dc=lit'
82
- object_class 'person'
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
- def test_authenticate_with_missing_credentials
89
- ldap = connect
90
- assert_nil ldap.authenticate(nil, nil)
91
- assert_nil ldap.authenticate('', '')
92
- assert_nil ldap.authenticate('user', ' ')
93
- end
94
-
95
- def test_authenticate_user_not_found
96
- CONTEXT.merge!({
97
- :mock_ldap => MiniTest::Mock.new,
98
- :connect_calls => 0
99
- })
100
- ldap = connect
101
- def ldap.connect(dn, password)
102
- CONTEXT[:connect_calls] += 1
103
- raise unless 'cn=Directory Manager' == dn
104
- raise unless 'secr3t' == password
105
-
106
- clas = Net::LDAP::Filter.eq('objectClass', 'person')
107
- uid = Net::LDAP::Filter.eq('uid', 'alice@wonderland.lit')
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
- def test_authenticate_user_fails_bind
118
- CONTEXT.merge!({
119
- :credentials => [
120
- {:dn => 'cn=Directory Manager', :password => 'secr3t'},
121
- {:dn => ALICE_DN, :password => 'passw0rd'}
122
- ],
123
- :mock_ldap => MiniTest::Mock.new,
124
- :mock_entry => MiniTest::Mock.new,
125
- :connect_calls => 0
126
- })
127
- ldap = connect
128
- def ldap.connect(dn, password)
129
- credentials = CONTEXT[:credentials][CONTEXT[:connect_calls]]
130
- CONTEXT[:connect_calls] += 1
131
- raise unless credentials[:dn] == dn && credentials[:password] == password
132
-
133
- clas = Net::LDAP::Filter.eq('objectClass', 'person')
134
- uid = Net::LDAP::Filter.eq('uid', 'alice@wonderland.lit')
135
-
136
- entry = CONTEXT[:mock_entry]
137
- entry.expect(:dn, ALICE_DN)
138
-
139
- mock = CONTEXT[:mock_ldap]
140
- mock.expect(:search, [entry], [{:attributes => ['cn', 'mail'], :filter => clas & uid}])
141
- mock.expect(:bind, false)
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
- def test_authenticate_success
150
- CONTEXT.merge!({
151
- :credentials => [
152
- {:dn => 'cn=Directory Manager', :password => 'secr3t'},
153
- {:dn => ALICE_DN, :password => 'passw0rd'}
154
- ],
155
- :mock_ldap => MiniTest::Mock.new,
156
- :mock_entry => MiniTest::Mock.new,
157
- :connect_calls => 0
158
- })
159
- ldap = connect
160
- def ldap.connect(dn, password)
161
- credentials = CONTEXT[:credentials][CONTEXT[:connect_calls]]
162
- CONTEXT[:connect_calls] += 1
163
- raise unless credentials[:dn] == dn && credentials[:password] == password
164
-
165
- clas = Net::LDAP::Filter.eq('objectClass', 'person')
166
- uid = Net::LDAP::Filter.eq('uid', 'alice@wonderland.lit')
167
-
168
- entry = CONTEXT[:mock_entry]
169
- entry.expect(:dn, ALICE_DN)
170
- entry.expect(:[], ['Alice Liddell'], ['cn'])
171
-
172
- mock = CONTEXT[:mock_ldap]
173
- mock.expect(:search, [entry], [{:attributes => ['cn', 'mail'], :filter => clas & uid}])
174
- mock.expect(:bind, true)
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
@@ -6,10 +6,9 @@ class MockRedis
6
6
 
7
7
  # Mimic em-hiredis behavior.
8
8
  def self.defer(method)
9
- old = "_deferred_#{method}"
10
- alias_method old, method
9
+ old = instance_method(method)
11
10
  define_method method do |*args, &block|
12
- result = method(old).call(*args)
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) }
@@ -4,7 +4,7 @@ require 'storage_tests'
4
4
  require 'vines'
5
5
  require 'minitest/autorun'
6
6
 
7
- class StorageTest < MiniTest::Unit::TestCase
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
- def test_authenticate_with_ldap_missing_password
43
- StorageTests::EMLoop.new do
44
- storage = MockLdapStorage.new
45
- user = storage.authenticate(ALICE, '')
46
- assert_nil user
47
- assert_equal 0, storage.authenticate_calls
48
- assert_equal 0, storage.find_user_calls
49
- assert_equal 0, storage.save_user_calls
50
- assert_nil storage.ldap.auth # ldap never called
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
- def test_authenticate_with_ldap_bad_password
55
- StorageTests::EMLoop.new do
56
- storage = MockLdapStorage.new
57
- storage.ldap.user = nil
58
- user = storage.authenticate(ALICE, 'bogus')
59
- assert_nil user
60
- assert_equal 0, storage.authenticate_calls
61
- assert_equal 0, storage.find_user_calls
62
- assert_equal 0, storage.save_user_calls
63
- assert_equal [ALICE, 'bogus'], storage.ldap.auth.first
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
- def test_authenticate_with_ldap_save_user_to_database
83
- StorageTests::EMLoop.new do
84
- alice = Vines::User.new(:jid => ALICE)
85
- storage = MockLdapStorage.new
86
- storage.ldap.user = alice
87
- user = storage.authenticate(ALICE, 'secr3t')
88
- refute_nil user
89
- assert_equal ALICE, user.jid.to_s
90
- assert_equal 0, storage.authenticate_calls
91
- assert_equal 1, storage.find_user_calls
92
- assert_equal 1, storage.save_user_calls
93
- assert_equal [ALICE, 'secr3t'], storage.ldap.auth.first
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.3
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-16 00:00:00.000000000Z
12
+ date: 2012-04-19 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
16
- requirement: &70110878851480 !ruby/object:Gem::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: *70110878851480
24
+ version_requirements: *70188360341400
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bcrypt-ruby
27
- requirement: &70110878850760 !ruby/object:Gem::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: *70110878850760
35
+ version_requirements: *70188360340640
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: em-http-request
38
- requirement: &70110878848940 !ruby/object:Gem::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: *70110878848940
46
+ version_requirements: *70188360339620
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: em-hiredis
49
- requirement: &70110878848100 !ruby/object:Gem::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: *70110878848100
57
+ version_requirements: *70188360334900
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: eventmachine
60
- requirement: &70110878847340 !ruby/object:Gem::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: *70110878847340
68
+ version_requirements: *70188360333880
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: http_parser.rb
71
- requirement: &70110878846460 !ruby/object:Gem::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: *70110878846460
79
+ version_requirements: *70188360332740
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: mongo
82
- requirement: &70110878845140 !ruby/object:Gem::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: *70110878845140
90
+ version_requirements: *70188360331500
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: bson_ext
93
- requirement: &70110878844340 !ruby/object:Gem::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: *70110878844340
101
+ version_requirements: *70188360330140
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: net-ldap
104
- requirement: &70110878843460 !ruby/object:Gem::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.2.2
109
+ version: 0.3.1
110
110
  type: :runtime
111
111
  prerelease: false
112
- version_requirements: *70110878843460
112
+ version_requirements: *70188360329300
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: nokogiri
115
- requirement: &70110878842540 !ruby/object:Gem::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: *70110878842540
123
+ version_requirements: *70188360328540
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: minitest
126
- requirement: &70110878841520 !ruby/object:Gem::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: *70110878841520
134
+ version_requirements: *70188360327640
135
135
  - !ruby/object:Gem::Dependency
136
136
  name: coffee-script
137
- requirement: &70110878840300 !ruby/object:Gem::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: *70110878840300
145
+ version_requirements: *70188360326740
146
146
  - !ruby/object:Gem::Dependency
147
147
  name: coffee-script-source
148
- requirement: &70110878839260 !ruby/object:Gem::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: *70110878839260
156
+ version_requirements: *70188360326200
157
157
  - !ruby/object:Gem::Dependency
158
158
  name: uglifier
159
- requirement: &70110878838580 !ruby/object:Gem::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: *70110878838580
167
+ version_requirements: *70188360325340
168
168
  - !ruby/object:Gem::Dependency
169
169
  name: rake
170
- requirement: &70110878837720 !ruby/object:Gem::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: *70110878837720
178
+ version_requirements: *70188360324400
179
179
  - !ruby/object:Gem::Dependency
180
180
  name: sqlite3
181
- requirement: &70110878836460 !ruby/object:Gem::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: *70110878836460
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