rails3-restful-authentication 3.0.1

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.
Files changed (54) hide show
  1. data/CHANGELOG +70 -0
  2. data/README.textile +176 -0
  3. data/Rakefile +32 -0
  4. data/TODO +15 -0
  5. data/init.rb +3 -0
  6. data/lib/authentication.rb +40 -0
  7. data/lib/authentication/by_cookie_token.rb +73 -0
  8. data/lib/authentication/by_password.rb +64 -0
  9. data/lib/authorization.rb +14 -0
  10. data/lib/authorization/aasm_roles.rb +63 -0
  11. data/lib/authorization/stateful_roles.rb +62 -0
  12. data/lib/generators/authenticated/USAGE +1 -0
  13. data/lib/generators/authenticated/authenticated_generator.rb +524 -0
  14. data/lib/generators/authenticated/templates/_model_partial.html.erb +8 -0
  15. data/lib/generators/authenticated/templates/activation.erb +3 -0
  16. data/lib/generators/authenticated/templates/authenticated_system.rb +189 -0
  17. data/lib/generators/authenticated/templates/authenticated_test_helper.rb +22 -0
  18. data/lib/generators/authenticated/templates/controller.rb +41 -0
  19. data/lib/generators/authenticated/templates/features/accounts.feature +109 -0
  20. data/lib/generators/authenticated/templates/features/sessions.feature +134 -0
  21. data/lib/generators/authenticated/templates/features/step_definitions/ra_env.rb +9 -0
  22. data/lib/generators/authenticated/templates/features/step_definitions/ra_navigation_steps.rb +48 -0
  23. data/lib/generators/authenticated/templates/features/step_definitions/ra_resource_steps.rb +178 -0
  24. data/lib/generators/authenticated/templates/features/step_definitions/ra_response_steps.rb +169 -0
  25. data/lib/generators/authenticated/templates/features/step_definitions/rest_auth_features_helper.rb +81 -0
  26. data/lib/generators/authenticated/templates/features/step_definitions/user_steps.rb +131 -0
  27. data/lib/generators/authenticated/templates/helper.rb +2 -0
  28. data/lib/generators/authenticated/templates/login.html.erb +16 -0
  29. data/lib/generators/authenticated/templates/mailer.rb +26 -0
  30. data/lib/generators/authenticated/templates/migration.rb +26 -0
  31. data/lib/generators/authenticated/templates/model.rb +87 -0
  32. data/lib/generators/authenticated/templates/model_controller.rb +83 -0
  33. data/lib/generators/authenticated/templates/model_helper.rb +93 -0
  34. data/lib/generators/authenticated/templates/model_helper_spec.rb +158 -0
  35. data/lib/generators/authenticated/templates/observer.rb +11 -0
  36. data/lib/generators/authenticated/templates/signup.html.erb +19 -0
  37. data/lib/generators/authenticated/templates/signup_notification.erb +8 -0
  38. data/lib/generators/authenticated/templates/site_keys.rb +38 -0
  39. data/lib/generators/authenticated/templates/spec/controllers/access_control_spec.rb +101 -0
  40. data/lib/generators/authenticated/templates/spec/controllers/authenticated_system_spec.rb +102 -0
  41. data/lib/generators/authenticated/templates/spec/controllers/sessions_controller_spec.rb +127 -0
  42. data/lib/generators/authenticated/templates/spec/controllers/users_controller_spec.rb +131 -0
  43. data/lib/generators/authenticated/templates/spec/fixtures/users.yml +60 -0
  44. data/lib/generators/authenticated/templates/spec/helpers/users_helper_spec.rb +141 -0
  45. data/lib/generators/authenticated/templates/spec/models/user_spec.rb +227 -0
  46. data/lib/generators/authenticated/templates/test/functional_test.rb +82 -0
  47. data/lib/generators/authenticated/templates/test/mailer_test.rb +32 -0
  48. data/lib/generators/authenticated/templates/test/model_functional_test.rb +93 -0
  49. data/lib/generators/authenticated/templates/test/unit_test.rb +164 -0
  50. data/lib/restful_authentication.rb +3 -0
  51. data/lib/tasks/auth.rake +33 -0
  52. data/lib/trustification.rb +14 -0
  53. data/lib/trustification/email_validation.rb +20 -0
  54. metadata +130 -0
@@ -0,0 +1,158 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ include ApplicationHelper
3
+ include <%= model_controller_class_name %>Helper
4
+
5
+ describe "<%= model_controller_class_name %>Helper.link_to_<%= file_name %>" do
6
+ before do
7
+ @<%= file_name %> = <%= class_name %>.new({
8
+ :name => '<%= class_name %> Name',
9
+ :login => '<%= file_name %>_name',
10
+ })
11
+ @<%= file_name %>.id = 1 # set non-attr_accessible specifically
12
+ end
13
+
14
+ it "should give an error on a nil <%= file_name %>" do
15
+ lambda { link_to_<%= file_name %>(nil) }.should raise_error('Invalid <%= file_name %>')
16
+ end
17
+
18
+ it "should link to the given <%= file_name %>" do
19
+ link_to_<%= file_name %>(@<%= file_name %>).should have_tag("a[href='/<%= table_name %>/1']")
20
+ end
21
+
22
+ it "should use given link text if :content_text is specified" do
23
+ link_to_<%= file_name %>(@<%= file_name %>, :content_text => 'Hello there!').should have_tag("a", 'Hello there!')
24
+ end
25
+
26
+ it "should use the login as link text with no :content_method specified" do
27
+ link_to_<%= file_name %>(@<%= file_name %>).should have_tag("a", '<%= file_name %>_name')
28
+ end
29
+
30
+ it "should use the name as link text with :content_method => :name" do
31
+ link_to_<%= file_name %>(@<%= file_name %>, :content_method => :name).should have_tag("a", '<%= class_name %> Name')
32
+ end
33
+
34
+ it "should use the login as title with no :title_method specified" do
35
+ link_to_<%= file_name %>(@<%= file_name %>).should have_tag("a[title='<%= file_name %>_name']")
36
+ end
37
+
38
+ it "should use the name as link title with :content_method => :name" do
39
+ link_to_<%= file_name %>(@<%= file_name %>, :title_method => :name).should have_tag("a[title='<%= class_name %> Name']")
40
+ end
41
+
42
+ it "should have nickname as a class by default" do
43
+ link_to_<%= file_name %>(@<%= file_name %>).should have_tag("a.nickname")
44
+ end
45
+
46
+ it "should take other classes and no longer have the nickname class" do
47
+ result = link_to_<%= file_name %>(@<%= file_name %>, :class => 'foo bar')
48
+ result.should have_tag("a.foo")
49
+ result.should have_tag("a.bar")
50
+ end
51
+ end
52
+
53
+ describe "<%= model_controller_class_name %>Helper.link_to_signin_with_IP" do
54
+ before do
55
+ end
56
+
57
+ it "should link to the signin_path" do
58
+ link_to_signin_with_IP().should have_tag("a[href='/signin']")
59
+ end
60
+
61
+ it "should use given link text if :content_text is specified" do
62
+ link_to_signin_with_IP(:content_text => 'Hello there!').should have_tag("a", 'Hello there!')
63
+ end
64
+
65
+ it "should use the login as link text with no :content_method specified" do
66
+ link_to_signin_with_IP().should have_tag("a", '0.0.0.0')
67
+ end
68
+
69
+ it "should use the ip address as title" do
70
+ link_to_signin_with_IP().should have_tag("a[title='0.0.0.0']")
71
+ end
72
+
73
+ it "should by default be like school in summer and have no class" do
74
+ link_to_signin_with_IP().should_not have_tag("a.nickname")
75
+ end
76
+
77
+ it "should have some class if you tell it to" do
78
+ result = link_to_signin_with_IP(:class => 'foo bar')
79
+ result.should have_tag("a.foo")
80
+ result.should have_tag("a.bar")
81
+ end
82
+ end
83
+
84
+ describe "<%= model_controller_class_name %>Helper.link_to_current_<%= file_name %>, When logged in" do
85
+ fixtures :<%= table_name %>
86
+ include AuthenticatedTestHelper
87
+ before do
88
+ login_as(:quentin)
89
+ end
90
+
91
+ it "should link to the given <%= file_name %>" do
92
+ link_to_current_<%= file_name %>().should have_tag("a[href='/<%= table_name %>/1']")
93
+ end
94
+
95
+ it "should use given link text if :content_text is specified" do
96
+ link_to_current_user(:content_text => 'Hello there!').should have_tag("a", 'Hello there!')
97
+ end
98
+
99
+ it "should use the login as link text with no :content_method specified" do
100
+ link_to_current_user().should have_tag("a", 'quentin')
101
+ end
102
+
103
+ it "should use the name as link text with :content_method => :name" do
104
+ link_to_current_user(:content_method => :name).should have_tag("a", 'Quentin')
105
+ end
106
+
107
+ it "should use the login as title with no :title_method specified" do
108
+ link_to_current_user().should have_tag("a[title='quentin']")
109
+ end
110
+
111
+ it "should use the name as link title with :content_method => :name" do
112
+ link_to_current_user(:title_method => :name).should have_tag("a[title='Quentin']")
113
+ end
114
+
115
+ it "should have nickname as a class" do
116
+ link_to_current_user().should have_tag("a.nickname")
117
+ end
118
+
119
+ it "should take other classes and no longer have the nickname class" do
120
+ result = link_to_current_user(:class => 'foo bar')
121
+ result.should have_tag("a.foo")
122
+ result.should have_tag("a.bar")
123
+ end
124
+ end
125
+
126
+
127
+
128
+ describe "<%= model_controller_class_name %>Helper.link_to_current_user, When logged out" do
129
+ include AuthenticatedTestHelper
130
+ before do
131
+ end
132
+
133
+ it "should link to the signin_path" do
134
+ link_to_current_user().should have_tag("a[href='/signin']")
135
+ end
136
+
137
+ it "should use given link text if :content_text is specified" do
138
+ link_to_current_user(:content_text => 'Hello there!').should have_tag("a", 'Hello there!')
139
+ end
140
+
141
+ it "should use the IP address as link text with no :content_method specified" do
142
+ link_to_current_user().should have_tag("a", '0.0.0.0')
143
+ end
144
+
145
+ it "should use the ip address as title" do
146
+ link_to_current_user().should have_tag("a[title='0.0.0.0']")
147
+ end
148
+
149
+ it "should by default be like school in summer and have no class" do
150
+ link_to_current_user().should_not have_tag("a.nickname")
151
+ end
152
+
153
+ it "should have some class if you tell it to" do
154
+ result = link_to_current_user(:class => 'foo bar')
155
+ result.should have_tag("a.foo")
156
+ result.should have_tag("a.bar")
157
+ end
158
+ end
@@ -0,0 +1,11 @@
1
+ class <%= class_name %>Observer < ActiveRecord::Observer
2
+
3
+ def after_create(<%= file_name %>)
4
+ <%= class_name %>Mailer.signup_notification(<%= file_name %>).deliver
5
+ end
6
+
7
+ def after_save(<%= file_name %>)
8
+ <% if options[:include_activation] %><%= class_name %>Mailer.activation(<%= file_name %>).deliver if <%= file_name %>.recently_activated?<% end %>
9
+ end
10
+
11
+ end
@@ -0,0 +1,19 @@
1
+ <h1>Sign up as a new user</h1>
2
+ <%% @<%= file_name %>.password = @<%= file_name %>.password_confirmation = nil %>
3
+
4
+ <%%= error_messages_for :<%= file_name %> %>
5
+ <%%= form_for :<%= file_name %>, :url => <%= model_controller_routing_name %>_path do |f| -%>
6
+ <p><%%= label_tag 'login' %><br/>
7
+ <%%= f.text_field :login %></p>
8
+
9
+ <p><%%= label_tag 'email' %><br/>
10
+ <%%= f.text_field :email %></p>
11
+
12
+ <p><%%= label_tag 'password' %><br/>
13
+ <%%= f.password_field :password %></p>
14
+
15
+ <p><%%= label_tag 'password_confirmation', 'Confirm Password' %><br/>
16
+ <%%= f.password_field :password_confirmation %></p>
17
+
18
+ <p><%%= submit_tag 'Sign up' %></p>
19
+ <%% end -%>
@@ -0,0 +1,8 @@
1
+ Your account has been created.
2
+
3
+ Username: <%%=h @<%= file_name %>.login %>
4
+ Password: <%%=h @<%= file_name %>.password %>
5
+
6
+ Visit this url to activate your account:
7
+
8
+ <%%=h @url %>
@@ -0,0 +1,38 @@
1
+
2
+ # A Site key gives additional protection against a dictionary attack if your
3
+ # DB is ever compromised. With no site key, we store
4
+ # DB_password = hash(user_password, DB_user_salt)
5
+ # If your database were to be compromised you'd be vulnerable to a dictionary
6
+ # attack on all your stupid users' passwords. With a site key, we store
7
+ # DB_password = hash(user_password, DB_user_salt, Code_site_key)
8
+ # That means an attacker needs access to both your site's code *and* its
9
+ # database to mount an "offline dictionary attack.":http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/web-authentication.html
10
+ #
11
+ # It's probably of minor importance, but recommended by best practices: 'defense
12
+ # in depth'. Needless to say, if you upload this to github or the youtubes or
13
+ # otherwise place it in public view you'll kinda defeat the point. Your users'
14
+ # passwords are still secure, and the world won't end, but defense_in_depth -= 1.
15
+ #
16
+ # Please note: if you change this, all the passwords will be invalidated, so DO
17
+ # keep it someplace secure. Use the random value given or type in the lyrics to
18
+ # your favorite Jay-Z song or something; any moderately long, unpredictable text.
19
+ REST_AUTH_SITE_KEY = '<%= $rest_auth_site_key_from_generator %>'
20
+
21
+ # Repeated applications of the hash make brute force (even with a compromised
22
+ # database and site key) harder, and scale with Moore's law.
23
+ #
24
+ # bq. "To squeeze the most security out of a limited-entropy password or
25
+ # passphrase, we can use two techniques [salting and stretching]... that are
26
+ # so simple and obvious that they should be used in every password system.
27
+ # There is really no excuse not to use them." http://tinyurl.com/37lb73
28
+ # Practical Security (Ferguson & Scheier) p350
29
+ #
30
+ # A modest 10 foldings (the default here) adds 3ms. This makes brute forcing 10
31
+ # times harder, while reducing an app that otherwise serves 100 reqs/s to 78 signin
32
+ # reqs/s, an app that does 10reqs/s to 9.7 reqs/s
33
+ #
34
+ # More:
35
+ # * http://www.owasp.org/index.php/Hashing_Java
36
+ # * "An Illustrated Guide to Cryptographic Hashes":http://www.unixwiz.net/techtips/iguide-crypto-hashes.html
37
+
38
+ REST_AUTH_DIGEST_STRETCHES = <%= $rest_auth_digest_stretches_from_generator %>
@@ -0,0 +1,101 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+ # Be sure to include AuthenticatedTestHelper in spec/spec_helper.rb instead
3
+ # Then, you can remove it from this and the units test.
4
+ include AuthenticatedTestHelper
5
+
6
+ #
7
+ # A test controller with and without access controls
8
+ #
9
+ class AccessControlTestController < ApplicationController
10
+ before_filter :login_required, :only => :login_is_required
11
+ def login_is_required
12
+ respond_to do |format|
13
+ @foo = { 'success' => params[:format]||'no fmt given'}
14
+ format.html do render :text => "success" end
15
+ format.xml do render :xml => @foo, :status => :ok end
16
+ format.json do render :json => @foo, :status => :ok end
17
+ end
18
+ end
19
+ def login_not_required
20
+ respond_to do |format|
21
+ @foo = { 'success' => params[:format]||'no fmt given'}
22
+ format.html do render :text => "success" end
23
+ format.xml do render :xml => @foo, :status => :ok end
24
+ format.json do render :json => @foo, :status => :ok end
25
+ end
26
+ end
27
+ end
28
+
29
+ #
30
+ # Access Control
31
+ #
32
+
33
+ ACCESS_CONTROL_FORMATS = [
34
+ ['html', "success"],
35
+ ['xml', "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<hash>\n <success>xml</success>\n</hash>\n"],
36
+ ['json', "{\"success\":\"json\"}"],]
37
+ ACCESS_CONTROL_AM_I_LOGGED_IN = [
38
+ [:i_am_logged_in, :quentin],
39
+ [:i_am_not_logged_in, nil],]
40
+ ACCESS_CONTROL_IS_LOGIN_REQD = [
41
+ :login_not_required,
42
+ :login_is_required,]
43
+
44
+ describe AccessControlTestController do
45
+ fixtures :users
46
+ before do
47
+ # is there a better way to do this?
48
+ begin
49
+ _routes = Rails.application.class.routes
50
+ _routes.disable_clear_and_finalize = true
51
+ _routes.clear!
52
+ Rails.application.class.routes_reloader.paths.each{ |path| load(path) }
53
+ _routes.draw do
54
+ match 'login_is_required' => 'access_control_test#login_is_required'
55
+ match 'login_not_required' => 'access_control_test#login_not_required'
56
+ end
57
+ ActiveSupport.on_load(:action_controller) { _routes.finalize! }
58
+ ensure
59
+ _routes.disable_clear_and_finalize = false
60
+ end
61
+ end
62
+
63
+ ACCESS_CONTROL_FORMATS.each do |format, success_text|
64
+ ACCESS_CONTROL_AM_I_LOGGED_IN.each do |logged_in_status, user_login|
65
+ ACCESS_CONTROL_IS_LOGIN_REQD.each do |login_reqd_status|
66
+ describe "requesting #{format.blank? ? 'html' : format}; #{logged_in_status.to_s.humanize} and #{login_reqd_status.to_s.humanize}" do
67
+ before do
68
+ controller.send(:logout_keeping_session!)
69
+ @user = format.blank? ? login_as(user_login) : authorize_as(user_login)
70
+ get login_reqd_status.to_s, :format => format
71
+ end
72
+
73
+ if ((login_reqd_status == :login_not_required) ||
74
+ (login_reqd_status == :login_is_required && logged_in_status == :i_am_logged_in))
75
+ it "succeeds" do
76
+ response.body.should == success_text
77
+ response.code.to_s.should == '200'
78
+ end
79
+
80
+ elsif (login_reqd_status == :login_is_required && logged_in_status == :i_am_not_logged_in)
81
+ if ['html', ''].include? format
82
+ it "redirects me to the log in page" do
83
+ response.should redirect_to('/session/new')
84
+ end
85
+ else
86
+ it "returns 'Access denied' and a 406 (Access Denied) status code" do
87
+ response.should contain("HTTP Basic: Access denied.")
88
+ response.code.to_s.should == '401'
89
+ end
90
+ end
91
+
92
+ else
93
+ warn "Oops no case for #{format} and #{logged_in_status.to_s.humanize} and #{login_reqd_status.to_s.humanize}"
94
+ end
95
+ end # describe
96
+
97
+ end
98
+ end
99
+ end # cases
100
+
101
+ end
@@ -0,0 +1,102 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ # Be sure to include AuthenticatedTestHelper in spec/spec_helper.rb instead
4
+ # Then, you can remove it from this and the units test.
5
+ include AuthenticatedTestHelper
6
+ include AuthenticatedSystem
7
+ def action_name() end
8
+
9
+ describe SessionsController do
10
+ fixtures :users
11
+
12
+ before do
13
+ # FIXME -- sessions controller not testing xml logins
14
+ stub!(:authenticate_with_http_basic).and_return nil
15
+ end
16
+ describe "logout_killing_session!" do
17
+ before do
18
+ login_as :quentin
19
+ stub!(:reset_session)
20
+ end
21
+ it 'resets the session' do should_receive(:reset_session); logout_killing_session! end
22
+ it 'kills my auth_token cookie' do should_receive(:kill_remember_cookie!); logout_killing_session! end
23
+ it 'nils the current user' do logout_killing_session!; current_user.should be_nil end
24
+ it 'kills :user_id session' do
25
+ session.stub!(:[]=)
26
+ session.should_receive(:[]=).with(:user_id, nil).at_least(:once)
27
+ logout_killing_session!
28
+ end
29
+ it 'forgets me' do
30
+ current_user.remember_me
31
+ current_user.remember_token.should_not be_nil; current_user.remember_token_expires_at.should_not be_nil
32
+ User.find(1).remember_token.should_not be_nil; User.find(1).remember_token_expires_at.should_not be_nil
33
+ logout_killing_session!
34
+ User.find(1).remember_token.should be_nil; User.find(1).remember_token_expires_at.should be_nil
35
+ end
36
+ end
37
+
38
+ describe "logout_keeping_session!" do
39
+ before do
40
+ login_as :quentin
41
+ stub!(:reset_session)
42
+ end
43
+ it 'does not reset the session' do should_not_receive(:reset_session); logout_keeping_session! end
44
+ it 'kills my auth_token cookie' do should_receive(:kill_remember_cookie!); logout_keeping_session! end
45
+ it 'nils the current user' do logout_keeping_session!; current_user.should be_nil end
46
+ it 'kills :user_id session' do
47
+ session.stub!(:[]=)
48
+ session.should_receive(:[]=).with(:user_id, nil).at_least(:once)
49
+ logout_keeping_session!
50
+ end
51
+ it 'forgets me' do
52
+ current_user.remember_me
53
+ current_user.remember_token.should_not be_nil; current_user.remember_token_expires_at.should_not be_nil
54
+ User.find(1).remember_token.should_not be_nil; User.find(1).remember_token_expires_at.should_not be_nil
55
+ logout_keeping_session!
56
+ User.find(1).remember_token.should be_nil; User.find(1).remember_token_expires_at.should be_nil
57
+ end
58
+ end
59
+
60
+ describe 'When logged out' do
61
+ it "should not be authorized?" do
62
+ authorized?().should be_false
63
+ end
64
+ end
65
+
66
+ #
67
+ # Cookie Login
68
+ #
69
+ describe "Logging in by cookie" do
70
+ def set_remember_token token, time
71
+ @user[:remember_token] = token;
72
+ @user[:remember_token_expires_at] = time
73
+ @user.save!
74
+ end
75
+ before do
76
+ @user = User.find(:first);
77
+ set_remember_token 'hello!', 5.minutes.from_now
78
+ end
79
+ it 'logs in with cookie' do
80
+ stub!(:cookies).and_return({ :auth_token => 'hello!' })
81
+ logged_in?.should be_true
82
+ end
83
+
84
+ it 'fails cookie login with bad cookie' do
85
+ should_receive(:cookies).at_least(:once).and_return({ :auth_token => 'i_haxxor_joo' })
86
+ logged_in?.should_not be_true
87
+ end
88
+
89
+ it 'fails cookie login with no cookie' do
90
+ set_remember_token nil, nil
91
+ should_receive(:cookies).at_least(:once).and_return({ })
92
+ logged_in?.should_not be_true
93
+ end
94
+
95
+ it 'fails expired cookie login' do
96
+ set_remember_token 'hello!', 5.minutes.ago
97
+ stub!(:cookies).and_return({ :auth_token => 'hello!' })
98
+ logged_in?.should_not be_true
99
+ end
100
+ end
101
+
102
+ end
@@ -0,0 +1,127 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ # Be sure to include AuthenticatedTestHelper in spec/spec_helper.rb instead
4
+ # Then, you can remove it from this and the units test.
5
+ include AuthenticatedTestHelper
6
+
7
+ describe SessionsController do
8
+ fixtures :users
9
+ before do
10
+ @user = mock_user
11
+ @login_params = { :login => 'quentin', :password => 'test' }
12
+ User.stub!(:authenticate).with(@login_params[:login], @login_params[:password]).and_return(@user)
13
+ end
14
+ def do_create
15
+ post :create, @login_params
16
+ end
17
+ describe "on successful login," do
18
+ [ [:nil, nil, nil],
19
+ [:expired, 'valid_token', 15.minutes.ago],
20
+ [:different, 'i_haxxor_joo', 15.minutes.from_now],
21
+ [:valid, 'valid_token', 15.minutes.from_now]
22
+ ].each do |has_request_token, token_value, token_expiry|
23
+ [ true, false ].each do |want_remember_me|
24
+ describe "my request cookie token is #{has_request_token.to_s}," do
25
+ describe "and ask #{want_remember_me ? 'to' : 'not to'} be remembered" do
26
+ before do
27
+ @ccookies = mock('cookies')
28
+ controller.stub!(:cookies).and_return(@ccookies)
29
+ @ccookies.stub!(:[]).with(:auth_token).and_return(token_value)
30
+ @ccookies.stub!(:delete).with(:auth_token)
31
+ @ccookies.stub!(:[]=)
32
+ @user.stub!(:remember_me)
33
+ @user.stub!(:refresh_token)
34
+ @user.stub!(:forget_me)
35
+ @user.stub!(:remember_token).and_return(token_value)
36
+ @user.stub!(:remember_token_expires_at).and_return(token_expiry)
37
+ @user.stub!(:remember_token?).and_return(has_request_token == :valid)
38
+ if want_remember_me
39
+ @login_params[:remember_me] = '1'
40
+ else
41
+ @login_params[:remember_me] = '0'
42
+ end
43
+ end
44
+ it "kills existing login" do controller.should_receive(:logout_keeping_session!); do_create; end
45
+ it "authorizes me" do do_create; controller.send(:authorized?).should be_true; end
46
+ it "logs me in" do do_create; controller.send(:logged_in?).should be_true end
47
+ it "greets me nicely" do do_create; flash[:notice].should =~ /success/i end
48
+ it "sets/resets/expires cookie" do controller.should_receive(:handle_remember_cookie!).with(want_remember_me); do_create end
49
+ it "sends a cookie" do controller.should_receive(:send_remember_cookie!); do_create end
50
+ it 'redirects to the home page' do do_create; response.should redirect_to('/') end
51
+ it "does not reset my session" do controller.should_not_receive(:reset_session).and_return nil; do_create end # change if you uncomment the reset_session path
52
+ if (has_request_token == :valid)
53
+ it 'does not make new token' do @user.should_not_receive(:remember_me); do_create end
54
+ it 'does refresh token' do @user.should_receive(:refresh_token); do_create end
55
+ it "sets an auth cookie" do do_create; end
56
+ else
57
+ if want_remember_me
58
+ it 'makes a new token' do @user.should_receive(:remember_me); do_create end
59
+ it "does not refresh token" do @user.should_not_receive(:refresh_token); do_create end
60
+ it "sets an auth cookie" do do_create; end
61
+ else
62
+ it 'does not make new token' do @user.should_not_receive(:remember_me); do_create end
63
+ it 'does not refresh token' do @user.should_not_receive(:refresh_token); do_create end
64
+ it 'kills user token' do @user.should_receive(:forget_me); do_create end
65
+ end
66
+ end
67
+ end # inner describe
68
+ end
69
+ end
70
+ end
71
+ end
72
+
73
+ describe "on failed login" do
74
+ before do
75
+ User.should_receive(:authenticate).with(anything(), anything()).and_return(nil)
76
+ login_as :quentin
77
+ end
78
+ it 'logs out keeping session' do controller.should_receive(:logout_keeping_session!); do_create end
79
+ it 'flashes an error' do do_create; flash[:error].should =~ /Couldn't log you in as 'quentin'/ end
80
+ it 'renders the log in page' do do_create; response.should render_template('new') end
81
+ it "doesn't log me in" do do_create; controller.send(:logged_in?).should == false end
82
+ it "doesn't send password back" do
83
+ @login_params[:password] = 'FROBNOZZ'
84
+ do_create
85
+ response.should_not contain(/FROBNOZZ/i)
86
+ end
87
+ end
88
+
89
+ describe "on signout" do
90
+ def do_destroy
91
+ get :destroy
92
+ end
93
+ before do
94
+ login_as :quentin
95
+ end
96
+ it 'logs me out' do controller.should_receive(:logout_killing_session!); do_destroy end
97
+ it 'redirects me to the home page' do do_destroy; response.should be_redirect end
98
+ end
99
+
100
+ end
101
+
102
+ describe SessionsController do
103
+ describe "route recognition and generation" do
104
+ it "should generate params from GET /login correctly" do
105
+ {:get => '/login'}.should route_to(:controller => 'sessions', :action => 'new')
106
+ end
107
+ it "should generate params from POST /session correctly" do
108
+ {:post => '/session'}.should route_to(:controller => 'sessions', :action => 'create')
109
+ end
110
+ it "should generate params from DELETE /session correctly" do
111
+ {:delete => '/logout'}.should route_to(:controller => 'sessions', :action => 'destroy')
112
+ end
113
+ end
114
+
115
+ describe "named routing" do
116
+ before(:each) do
117
+ get :new
118
+ end
119
+ it "should route session_path() correctly" do
120
+ session_path().should == "/session"
121
+ end
122
+ it "should route new_session_path() correctly" do
123
+ new_session_path().should == "/session/new"
124
+ end
125
+ end
126
+
127
+ end