pasaporte 0.0.1 → 0.0.3

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.
@@ -0,0 +1,53 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestEditProfile < Pasaporte::WebTest
4
+ test 'should require login' do
5
+ get '/julik/edit'
6
+ assert_response :redirect
7
+ assert_redirected_to '/julik/signon'
8
+ end
9
+
10
+ test 'should preload profile' do
11
+ prelogin 'julik'
12
+ get '/julik/edit'
13
+ assert_response :success
14
+ assert_kind_of Profile, @assigns.profile
15
+ deny @assigns.profile.new_record?, "This is a presaved profile"
16
+ assert_match_body /Your profile/
17
+ end
18
+
19
+ test 'should show message and not save when posting faulty data' do
20
+ prelogin 'julik'
21
+ post '/julik/edit', :profile => {:openid_server => 'xyz'}
22
+
23
+ assert_response :success
24
+ assert_not_nil @assigns.err, "An error message should be assigned"
25
+
26
+ prof = @assigns.profile
27
+ prof.reload
28
+ assert_nil prof.openid_server, "Nothing should have been assigned"
29
+ end
30
+
31
+ test 'should redirect with success message when changing the profile succeeds' do
32
+ prelogin 'julik'
33
+ post '/julik/edit', :profile => {:email => 'trof@groff.com'}
34
+ assert_response :redirect
35
+ assert_not_nil @state.msg
36
+ assert_match /Changed/i, @state.msg
37
+ end
38
+
39
+ test 'default country should be selected when loading the profile page for the first time' do
40
+ prelogin 'joe-boss'
41
+
42
+ begin
43
+ c = Pasaporte::DEFAULT_COUNTRY
44
+ silence_warnings { Pasaporte.const_set(:DEFAULT_COUNTRY, 'us')}
45
+ get '/joe-boss/edit'
46
+ assert_response :success
47
+ assert_select 'option[value="us"][selected]', true
48
+ ensure
49
+ silence_warnings { Pasaporte.const_set(:DEFAULT_COUNTRY, c) }
50
+ end
51
+ end
52
+
53
+ end
@@ -1,16 +1,9 @@
1
- $:.reject! { |e| e.include? 'TextMate' }
2
1
  require File.dirname(__FILE__) + '/helper'
3
2
  require 'fileutils'
4
3
  require File.dirname(__FILE__) + '/testable_openid_fetcher'
5
4
  require 'openid/store/memory'
6
5
  require 'openid/extensions/sreg'
7
6
 
8
- class Object
9
- def own_methods
10
- raise (methods - Object.instance_methods).inspect
11
- end
12
- end
13
-
14
7
  class TestOpenid < Pasaporte::WebTest
15
8
  # We have to open up because it's the Fecther that's going
16
9
  # to make requests
@@ -50,12 +43,12 @@ class TestOpenid < Pasaporte::WebTest
50
43
  assert_select 'link[rel=openid.server]', true do | s |
51
44
  s = s.pop
52
45
  assert_equal "http://test.host/pasaporte/monsieur-hulot/openid", s.attributes["href"],
53
- "Should contain the delegate address for Monsieur Hulot"
46
+ "Should contain the endpoint address for Monsieur Hulot"
54
47
  end
55
48
  assert_select 'link[rel=openid.delegate]', true do | s |
56
49
  s = s.pop
57
- assert_equal "http://test.host/pasaporte/monsieur-hulot/openid", s.attributes["href"],
58
- "Should contain the endpoint address for Monsieur Hulot"
50
+ assert_equal "http://test.host/pasaporte/monsieur-hulot", s.attributes["href"],
51
+ "Should refer to itself"
59
52
  end
60
53
  end
61
54
 
@@ -82,7 +75,7 @@ class TestOpenid < Pasaporte::WebTest
82
75
  assert_match(/#{Regexp.escape(@return_to + '?openid1_claimed_id=')}(.+)#{Regexp.escape('&rp_nonce=')}(.+)/,
83
76
  response_params["openid.return_to"],
84
77
  "The return_to should be the one of the signup with a nonce")
85
- assert_equal "http://test.host/pasaporte/monsieur-hulot/openid",
78
+ assert_equal "http://test.host/pasaporte/monsieur-hulot",
86
79
  response_params["openid.identity"], "The identity is the server URL in this case"
87
80
  assert_equal "checkid_setup", response_params['openid.mode'],
88
81
  "The current mode is checkid_setup"
@@ -315,10 +308,24 @@ class TestOpenid < Pasaporte::WebTest
315
308
  assert_equal "Monsieur Hulot", sreg_response['fullname']
316
309
  end
317
310
 
311
+ def test_in_which_julik_wants_to_login_but_monsieur_hulot_is_logged_in_already
312
+ prelogin! "monsieur-hulot"
313
+
314
+ req = @consumer.begin("http://test.host/pasaporte/julik")
315
+ assert_kind_of OpenID::Consumer::CheckIDRequest, req
316
+ assert_nothing_raised { get_with_verbatim_url req.redirect_url(@trust_root, @return_to) }
317
+ assert_response :redirect
318
+ assert_redirected_to '/julik/signon'
319
+ assert_not_nil @state.pending_openid, "A pending OpenID request should have been "+
320
+ "placed in the session"
321
+ assert_nil @state.nickname, "The nickname should have been removed from the session"
322
+ assert_kind_of OpenID::Server::CheckIDRequest, @state.pending_openid
323
+ end
324
+
318
325
  private
319
326
  # Prelogins Monsieur Hulot into Pasaporte
320
- def prelogin!
321
- post '/monsieur-hulot/signon', :pass => 'monsieur-hulot'.reverse
327
+ def prelogin!(name = 'monsieur-hulot')
328
+ post('/%s/signon' % name, :pass => name.reverse)
322
329
  end
323
330
 
324
331
  # Preapproves tativille.fr as a site Monsieur Hulot trusts
@@ -1,7 +1,4 @@
1
1
  require File.dirname(__FILE__) + '/helper'
2
- require File.dirname(__FILE__) + '/testable_openid_fetcher'
3
-
4
- require 'flexmock'
5
2
 
6
3
  class TestProfilePage < Pasaporte::WebTest
7
4
  fixtures :pasaporte_profiles
@@ -126,28 +123,6 @@ class TestSignon < Pasaporte::WebTest
126
123
  end
127
124
  end
128
125
 
129
- class TestSignout < Pasaporte::WebTest
130
- def test_signout_should_silently_redirect_unless_signed_in
131
- get '/somebody/signout'
132
- assert_response :redirect
133
- assert_redirected_to '/somebody/signon'
134
- end
135
-
136
- def test_signout_should_erase_session_and_redirect
137
- flexmock(Pasaporte::AUTH).
138
- should_receive(:call).with("gemanges", "tairn", "test.host").once.and_return(true)
139
- post '/gemanges/signon', :pass => 'tairn'
140
- assert_response :redirect
141
- assert_equal 'gemanges', @state.nickname
142
-
143
- get '/gemanges/signout'
144
- assert_response :redirect
145
- assert_redirected_to '/gemanges/signon'
146
- assert_kind_of Camping::H, @state, "State should be reset with Camping::H"
147
- assert_equal %w( msg ), @state.keys, "State should only contain the message"
148
- end
149
- end
150
-
151
126
  class TestApprovalsPage < Pasaporte::WebTest
152
127
  fixtures :pasaporte_profiles, :pasaporte_approvals
153
128
  def test_approvals_page_requires_login
@@ -210,58 +185,6 @@ class TestAssets < Pasaporte::WebTest
210
185
  end
211
186
  end
212
187
 
213
- class TestProfileEditor < Pasaporte::WebTest
214
- test 'should require login' do
215
- get '/julik/edit'
216
- assert_response :redirect
217
- assert_redirected_to '/julik/signon'
218
- end
219
-
220
- test 'should preload profile' do
221
- prelogin 'julik'
222
- get '/julik/edit'
223
- assert_response :success
224
- assert_kind_of Profile, @assigns.profile
225
- deny @assigns.profile.new_record?, "This is a presaved profile"
226
- assert_match_body /Your profile/
227
- end
228
-
229
- test 'should show message and not save when posting faulty data' do
230
- prelogin 'julik'
231
- post '/julik/edit', :profile => {:openid_server => 'xyz'}
232
-
233
- assert_response :success
234
- assert_not_nil @assigns.err, "An error message should be assigned"
235
- assert_match /Cannot save/, @assigns.err, "The error message should describe the problem"
236
-
237
- prof = @assigns.profile
238
- prof.reload
239
- assert_nil prof.openid_server, "Nothing should have been assigned"
240
- end
241
-
242
- test 'should redirect with success message when changing the profile succeeds' do
243
- prelogin 'julik'
244
- post '/julik/edit', :profile => {:email => 'trof@groff.com'}
245
- assert_response :redirect
246
- assert_not_nil @state.msg
247
- assert_match /Changed/i, @state.msg
248
- end
249
-
250
- test 'default country should be selected when loading the profile page for the first time' do
251
- prelogin 'joe-boss'
252
-
253
- begin
254
- c = Pasaporte::DEFAULT_COUNTRY
255
- silence_warnings { Pasaporte.const_set(:DEFAULT_COUNTRY, 'us')}
256
- get '/joe-boss/edit'
257
- assert_response :success
258
- assert_select 'option[value="us"][selected]', true
259
- ensure
260
- silence_warnings { Pasaporte.const_set(:DEFAULT_COUNTRY, c) }
261
- end
262
- end
263
-
264
- end
265
188
 
266
189
  # class TestYadis < Pasaporte::WebTest
267
190
  # attr_reader :request, :response
@@ -291,32 +214,6 @@ end
291
214
  # end
292
215
  # end
293
216
 
294
- class TestPublicSignon < Pasaporte::WebTest
295
- fixtures :pasaporte_profiles
296
- test 'should present a login screen without predefined nickname' do
297
- get
298
- assert_response :success
299
- assert_select 'input[name="login"]', true
300
-
301
- flexmock(Pasaporte::AUTH).should_receive(:call).with("schtwo", "foo", "test.host").and_return(false)
302
-
303
- post '/', :login => 'schtwo', :pass => 'foo'
304
- assert_response :success
305
- assert_nil @state.nickname
306
- assert_select 'input[type="hidden"]', true
307
- "The response should include a hidden field now instead of a text field"
308
- end
309
-
310
- test 'should redirect to profile page for new users' do
311
- flexmock(Pasaporte::AUTH).should_receive(:call).with("unknown", "pfew", "test.host").and_return(true)
312
- post '/', :login => "unknown", :pass => "pfew"
313
- assert_response :redirect
314
- assert_not_nil Profile.find_by_nickname('unknown'), "A profile should have been created during login"
315
- assert_redirected_to '/unknown/prefs'
316
- end
317
-
318
- end
319
-
320
217
  # A littol auditte
321
218
  at_exit do
322
219
  missing = Pasaporte::Controllers.constants.reject do |c|
@@ -95,12 +95,13 @@ class TestProfile < Camping::ModelTest
95
95
  deny p.delegates_openid?, "Delegation is now turned off because we sent a bool switch of false"
96
96
  end
97
97
 
98
+ # This is how the new OpenID lib normalizes URIs, has to do with the variance in "what" can be an OpenID URL
98
99
  def test_normalizes_both_delegate_urls
99
100
  p = create('julik', DOMAIN,
100
101
  :openid_server => 'xxx.com', :openid_delegate => 'xyz.org/x')
101
- assert_equal 'http://xxx.com/', p.openid_server,
102
+ assert_equal 'xxx.com', p.openid_server,
102
103
  "The URL should be normalized with HTTP scheme and trailing slash"
103
- assert_equal 'http://xyz.org/x', p.openid_delegate,
104
+ assert_equal 'xyz.org/x', p.openid_delegate,
104
105
  "The URL should be normalized with HTTP scheme"
105
106
  end
106
107
 
@@ -0,0 +1,26 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestPublicSignon < Pasaporte::WebTest
4
+ fixtures :pasaporte_profiles
5
+ test 'should present a login screen without predefined nickname' do
6
+ get
7
+ assert_response :success
8
+ assert_select 'input[name="login"]', true
9
+
10
+ flexmock(Pasaporte::AUTH).should_receive(:call).with("schtwo", "foo", "test.host").and_return(false)
11
+
12
+ post '/', :login => 'schtwo', :pass => 'foo'
13
+ assert_response :success
14
+ assert_nil @state.nickname
15
+ assert_select 'input[value="schtwo"]', true
16
+ end
17
+
18
+ test 'should redirect to profile page for new users' do
19
+ flexmock(Pasaporte::AUTH).should_receive(:call).with("unknown", "pfew", "test.host").and_return(true)
20
+ post '/', :login => "unknown", :pass => "pfew"
21
+ assert_response :redirect
22
+ assert_not_nil Profile.find_by_nickname('unknown'), "A profile should have been created during login"
23
+ assert_redirected_to '/unknown/prefs'
24
+ end
25
+
26
+ end
@@ -6,8 +6,7 @@ class TestSettings < Camping::Test
6
6
  def test_application
7
7
  emit :throttle_for => 45.minutes
8
8
  assert_nothing_raised { Pasaporte.apply_config! }
9
- assert_equal 45.minutes, Pasaporte::THROTTLE_FOR, "The setting should have " +
10
- "been applied"
9
+ assert_equal 45.minutes, Pasaporte::THROTTLE_FOR, "The setting should have been applied"
11
10
  end
12
11
 
13
12
  def test_bail_on_unknowns
@@ -0,0 +1,24 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestSignout < Pasaporte::WebTest
4
+ def test_signout_should_silently_redirect_unless_signed_in
5
+ get '/somebody/signout'
6
+ assert_response :redirect
7
+ assert_redirected_to '/somebody/signon'
8
+ end
9
+
10
+ def test_signout_should_erase_session_and_redirect
11
+ flexmock(Pasaporte::AUTH).
12
+ should_receive(:call).with("gemanges", "tairn", "test.host").once.and_return(true)
13
+ post '/gemanges/signon', :pass => 'tairn'
14
+ assert_response :redirect
15
+ assert_equal 'gemanges', @state.nickname
16
+
17
+ get '/gemanges/signout'
18
+ assert_response :redirect
19
+ assert_redirected_to '/gemanges/signon'
20
+ assert_kind_of Camping::H, @state, "State should be reset with Camping::H"
21
+ # TODO: why err is still here??
22
+ assert_equal %w( msg err ), @state.keys, "State should only contain the message and error"
23
+ end
24
+ end
@@ -0,0 +1,54 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class TestTokenBox < Test::Unit::TestCase
4
+ def test_init
5
+ assert_nothing_raised { TokenBox.new }
6
+ end
7
+
8
+ def test_procurement
9
+ box = TokenBox.new
10
+ tok = box.procure!("abc")
11
+ assert_kind_of String, tok
12
+ assert_equal TokenBox::TOKEN_SIZE, tok.length
13
+ tokens = (0...30).map { box.procure!("abc") }.uniq
14
+ assert_equal 30, tokens.uniq.length, "All generated tokens should differ"
15
+ tokens.each do | tok |
16
+ assert_equal TokenBox::TOKEN_SIZE, tok.length
17
+ end
18
+ end
19
+
20
+ def test_validation_should_happen_once
21
+ box = TokenBox.new
22
+ tok = box.procure!("a")
23
+ assert_nothing_raised { box.validate!("a", tok) }
24
+ assert_raise(TokenBox::Invalid) { box.validate!("a", tok) }
25
+ end
26
+
27
+ def test_validation_should_work_for_the_request_only
28
+ box = TokenBox.new
29
+ tok = box.procure!("a")
30
+ assert_raise(TokenBox::Invalid) { box.validate!("b", tok) }
31
+ assert_nothing_raised { box.validate!("a", tok) }
32
+ end
33
+
34
+ def test_tokens_should_be_discarded
35
+ box = TokenBox.new
36
+ first = box.procure!("a")
37
+ TokenBox::MAX_TOKENS.times { box.procure!("a") }
38
+ assert_raise(TokenBox::Invalid) { box.validate!("a", first)}
39
+ end
40
+
41
+ def test_token_should_expire
42
+ box = TokenBox.new
43
+ begin
44
+ old, $VERBOSE, w = TokenBox::WINDOW, nil, $VERBOSE
45
+ TokenBox.const_set(:WINDOW, 2)
46
+ tok = box.procure!("a")
47
+ sleep(2.3)
48
+ assert_raise(TokenBox::Invalid) { box.validate!("a", tok)}
49
+ ensure
50
+ TokenBox.const_set(:WINDOW, old)
51
+ $VERBOSE = w
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,99 @@
1
+ $:.reject! { |e| e.include? 'TextMate' }
2
+ require File.dirname(__FILE__) + '/helper'
3
+ require 'fileutils'
4
+ require File.dirname(__FILE__) + '/testable_openid_fetcher'
5
+ require 'openid/store/memory'
6
+ require 'openid/extensions/sreg'
7
+
8
+ class TestWithPartialSSL < Pasaporte::WebTest
9
+ # We have to open up because it's the Fecther that's going
10
+ # to make requests
11
+ attr_reader :request, :response
12
+ fixtures :pasaporte_profiles
13
+
14
+ def setup
15
+ super
16
+ @fetcher = TestableOpenidFetcher.new(self)
17
+
18
+ OpenID.fetcher = @fetcher
19
+ OpenID::Util.logger = Pasaporte::LOGGER
20
+
21
+ @store = OpenID::Store::Memory.new
22
+ @openid_session = {}
23
+ init_consumer
24
+
25
+ @request.domain = 'test.host'
26
+
27
+ @trust_root = 'http://tativille.fr/wiki'
28
+ @return_to = 'http://tativille.fr/wiki/signup'
29
+ @hulot = Profile.find(1)
30
+ silence_warnings { Pasaporte.const_set(:PARTIAL_SSL, true) }
31
+ end
32
+
33
+ def teardown
34
+ # Delete all the associations created during the test case
35
+ JulikState::State.delete_all; Association.delete_all; Approval.delete_all; Throttle.delete_all
36
+ # Delete the store
37
+ FileUtils.rm_rf('openid-consumer-store')
38
+ # Call super for flexmock a.o.
39
+ silence_warnings { Pasaporte.const_set(:PARTIAL_SSL, false) }
40
+ super
41
+ end
42
+
43
+ def test_in_which_monsieur_hulot_is_not_logged_in_and_asked_for_login_after_setup_and_gets_bounced_to_ssl_page
44
+ req = @consumer.begin("http://test.host/pasaporte/monsieur-hulot")
45
+ assert_kind_of OpenID::Consumer::CheckIDRequest, req
46
+ assert_nothing_raised { get_with_verbatim_url req.redirect_url(@trust_root, @return_to) }
47
+ assert_response :redirect
48
+
49
+ redirection = @response.headers['Location']
50
+ assert_redirected_to '/monsieur-hulot/signon'
51
+ follow_redirect
52
+
53
+ assert_response :redirect
54
+ assert_match /^https/, @response.headers['Location'].to_s, "Signon should redirect to itself over HTTPS"
55
+
56
+ assert_not_nil @state.pending_openid, "A pending OpenID request should have been "+
57
+ "placed in the session"
58
+
59
+ # TODO: Verify that the cookie indeed gets transferred along to the SSL domain
60
+ assert_kind_of OpenID::Server::CheckIDRequest, @state.pending_openid
61
+ end
62
+
63
+ private
64
+
65
+ def init_consumer
66
+ @consumer = OpenID::Consumer.new(@openid_session, @store)
67
+ end
68
+ def decode_qs(qs)
69
+ qs.to_s.split(/\&/).inject({}) do | params, segment |
70
+ k, v = segment.split(/\=/).map{|s| Camping.un(s)}
71
+ params[k] = v; params
72
+ end
73
+ end
74
+ def response_to_hash
75
+ Hash[*@response.body.split(/\n/).map{|p| p.split(/\:/)}.flatten].with_indifferent_access
76
+ end
77
+ def redirect_path_and_params(t = nil)
78
+ # Camping conveniently places a URI object in the location header
79
+ uri = (t ? URI.parse(t) : @response.headers["Location"])
80
+ [uri.path, decode_qs(uri.query)]
81
+ end
82
+
83
+ def redirect_url_path_and_params(t = nil)
84
+ # Camping conveniently places a URI object in the location header
85
+ uri = (t ? URI.parse(t) : @response.headers["Location"])
86
+ uri_with_scheme, qry = uri.to_s.split(/\?/)
87
+
88
+ [uri_with_scheme, uri.path, decode_qs(qry)]
89
+ end
90
+
91
+ def get_with_verbatim_url(url)
92
+ get(*recompose(url))
93
+ end
94
+
95
+ def recompose(url)
96
+ u = URI.parse(url)
97
+ [u.path.gsub(/^\/pasaporte/, ''), decode_qs(u.query)]
98
+ end
99
+ end