restful_authentication 1.1.6

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 (64) hide show
  1. data/CHANGELOG +68 -0
  2. data/LICENSE +20 -0
  3. data/README.textile +232 -0
  4. data/Rakefile +54 -0
  5. data/TODO +15 -0
  6. data/generators/authenticated/USAGE +1 -0
  7. data/generators/authenticated/authenticated_generator.rb +493 -0
  8. data/generators/authenticated/lib/insert_routes.rb +69 -0
  9. data/generators/authenticated/templates/_model_partial.html.erb +8 -0
  10. data/generators/authenticated/templates/activation.erb +3 -0
  11. data/generators/authenticated/templates/authenticated_system.rb +189 -0
  12. data/generators/authenticated/templates/authenticated_test_helper.rb +12 -0
  13. data/generators/authenticated/templates/controller.rb +43 -0
  14. data/generators/authenticated/templates/features/accounts.feature +67 -0
  15. data/generators/authenticated/templates/features/sessions.feature +77 -0
  16. data/generators/authenticated/templates/features/step_definitions/ra_env.rb +7 -0
  17. data/generators/authenticated/templates/features/step_definitions/user_steps.rb +31 -0
  18. data/generators/authenticated/templates/helper.rb +2 -0
  19. data/generators/authenticated/templates/login.html.erb +14 -0
  20. data/generators/authenticated/templates/machinist_spec.rb +5 -0
  21. data/generators/authenticated/templates/machinist_test.rb +5 -0
  22. data/generators/authenticated/templates/mailer.rb +25 -0
  23. data/generators/authenticated/templates/migration.rb +24 -0
  24. data/generators/authenticated/templates/model.rb +83 -0
  25. data/generators/authenticated/templates/model_controller.rb +96 -0
  26. data/generators/authenticated/templates/model_helper.rb +93 -0
  27. data/generators/authenticated/templates/model_helper_spec.rb +157 -0
  28. data/generators/authenticated/templates/observer.rb +11 -0
  29. data/generators/authenticated/templates/signup.html.erb +19 -0
  30. data/generators/authenticated/templates/signup_notification.erb +8 -0
  31. data/generators/authenticated/templates/site_keys.rb +38 -0
  32. data/generators/authenticated/templates/spec/blueprints/user.rb +13 -0
  33. data/generators/authenticated/templates/spec/controllers/access_control_spec.rb +89 -0
  34. data/generators/authenticated/templates/spec/controllers/authenticated_system_spec.rb +107 -0
  35. data/generators/authenticated/templates/spec/controllers/sessions_controller_spec.rb +138 -0
  36. data/generators/authenticated/templates/spec/controllers/users_controller_spec.rb +197 -0
  37. data/generators/authenticated/templates/spec/fixtures/users.yml +60 -0
  38. data/generators/authenticated/templates/spec/helpers/users_helper_spec.rb +141 -0
  39. data/generators/authenticated/templates/spec/models/user_spec.rb +298 -0
  40. data/generators/authenticated/templates/tasks/auth.rake +33 -0
  41. data/generators/authenticated/templates/test/functional_test.rb +84 -0
  42. data/generators/authenticated/templates/test/mailer_test.rb +31 -0
  43. data/generators/authenticated/templates/test/model_functional_test.rb +91 -0
  44. data/generators/authenticated/templates/test/unit_test.rb +177 -0
  45. data/lib/authentication.rb +40 -0
  46. data/lib/authentication/by_cookie_token.rb +82 -0
  47. data/lib/authentication/by_password.rb +64 -0
  48. data/lib/authorization.rb +14 -0
  49. data/lib/authorization/aasm_roles.rb +64 -0
  50. data/lib/authorization/stateful_roles.rb +64 -0
  51. data/lib/restful_authentication.rb +6 -0
  52. data/lib/trustification.rb +14 -0
  53. data/lib/trustification/email_validation.rb +20 -0
  54. data/notes/AccessControl.txt +2 -0
  55. data/notes/Authentication.txt +5 -0
  56. data/notes/Authorization.txt +154 -0
  57. data/notes/RailsPlugins.txt +78 -0
  58. data/notes/SecurityFramework.graffle +0 -0
  59. data/notes/SecurityFramework.png +0 -0
  60. data/notes/SecurityPatterns.txt +163 -0
  61. data/notes/Tradeoffs.txt +126 -0
  62. data/notes/Trustification.txt +49 -0
  63. data/restful_authentication.gemspec +32 -0
  64. metadata +128 -0
@@ -0,0 +1,11 @@
1
+ class <%= class_name %>Observer < ActiveRecord::Observer
2
+ def after_create(<%= file_name %>)
3
+ <%= class_name %>Mailer.deliver_signup_notification(<%= file_name %>)
4
+ end
5
+
6
+ def after_save(<%= file_name %>)
7
+ <% if options[:include_activation] %>
8
+ <%= class_name %>Mailer.deliver_activation(<%= file_name %>) if <%= file_name %>.recently_activated?
9
+ <% end %>
10
+ end
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
+ <%% form_for :<%= file_name %>, :url => <%= model_controller_routing_name %>_path do |f| -%>
5
+ <%%= f.error_messages %>
6
+ <p><%%= f.label :login %><br/>
7
+ <%%= f.text_field :login %></p>
8
+
9
+ <p><%%= f.label :email %><br/>
10
+ <%%= f.text_field :email %></p>
11
+
12
+ <p><%%= f.label :password %><br/>
13
+ <%%= f.password_field :password %></p>
14
+
15
+ <p><%%= f.label :password_confirmation, 'Confirm Password' %><br/>
16
+ <%%= f.password_field :password_confirmation %></p>
17
+
18
+ <p><%%= f.submit '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,13 @@
1
+ <%= class_name %>.blueprint do
2
+ login { Faker::Internet.user_name }
3
+ password 'testing'
4
+ password_confirmation { password }
5
+ email { Faker::Internet.email }
6
+ <% if options[:include_activation] -%>
7
+ activation_code { nil }
8
+ activated_at { 5.days.ago }
9
+ <% end -%>
10
+ <% if options[:stateful] -%>
11
+ state { 'active' }
12
+ <% end -%>
13
+ end
@@ -0,0 +1,89 @@
1
+ require File.dirname(__FILE__) + '<%= ('/..'*controller_class_nesting_depth) + '/../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
+ ['', "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
+ before do
46
+ # is there a better way to do this?
47
+ ActionController::Routing::Routes.add_route '/login_is_required', :controller => 'access_control_test', :action => 'login_is_required'
48
+ ActionController::Routing::Routes.add_route '/login_not_required', :controller => 'access_control_test', :action => 'login_not_required'
49
+ end
50
+
51
+ ACCESS_CONTROL_FORMATS.each do |format, success_text|
52
+ ACCESS_CONTROL_AM_I_LOGGED_IN.each do |logged_in_status, <%= file_name %>_login|
53
+ ACCESS_CONTROL_IS_LOGIN_REQD.each do |login_reqd_status|
54
+ describe "requesting #{format.blank? ? 'html' : format}; #{logged_in_status.to_s.humanize} and #{login_reqd_status.to_s.humanize}" do
55
+ before do
56
+ logout_keeping_session!
57
+ @<%= file_name %> = format.blank? ? log_in : authorize if logged_in_status == :i_am_logged_in
58
+ get login_reqd_status.to_s, :format => format
59
+ end
60
+
61
+ if ((login_reqd_status == :login_not_required) ||
62
+ (login_reqd_status == :login_is_required && logged_in_status == :i_am_logged_in))
63
+ it "succeeds" do
64
+ response.should have_text(success_text)
65
+ response.code.to_s.should == '200'
66
+ end
67
+
68
+ elsif (login_reqd_status == :login_is_required && logged_in_status == :i_am_not_logged_in)
69
+ if ['html', ''].include? format
70
+ it "redirects me to the log in page" do
71
+ response.should redirect_to('/<%= controller_routing_path %>/new')
72
+ end
73
+ else
74
+ it "returns 'Access denied' and a 406 (Access Denied) status code" do
75
+ response.should have_text("HTTP Basic: Access denied.\n")
76
+ response.code.to_s.should == '401'
77
+ end
78
+ end
79
+
80
+ else
81
+ warn "Oops no case for #{format} and #{logged_in_status.to_s.humanize} and #{login_reqd_status.to_s.humanize}"
82
+ end
83
+ end # describe
84
+
85
+ end
86
+ end
87
+ end # cases
88
+
89
+ end
@@ -0,0 +1,107 @@
1
+ require File.dirname(__FILE__) + '<%= ('/..'*controller_class_nesting_depth) + '/../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 <%= controller_class_name %>Controller do
10
+ before do
11
+ # FIXME -- <%= controller_file_name %> controller not testing xml logins
12
+ stub!(:authenticate_with_http_basic).and_return nil
13
+ end
14
+ describe "logout_killing_session!" do
15
+ before do
16
+ log_in
17
+ stub!(:reset_session)
18
+ end
19
+ it 'resets the session' do should_receive(:reset_session); logout_killing_session! end
20
+ it 'kills my auth_token cookie' do should_receive(:kill_remember_cookie!); logout_killing_session! end
21
+ it 'nils the current <%= file_name %>' do logout_killing_session!; current_<%= file_name %>.should be_nil end
22
+ it 'kills :<%= file_name %>_id session' do
23
+ session.stub!(:[]=)
24
+ session.should_receive(:[]=).with(:<%= file_name %>_id, nil).at_least(:once)
25
+ logout_killing_session!
26
+ end
27
+ it 'forgets me' do
28
+ current_<%= file_name %>_id = current_<%= file_name %>.id
29
+ current_<%= file_name %>.remember_me
30
+ current_<%= file_name %>.remember_token.should_not be_nil
31
+ current_<%= file_name %>.remember_token_expires_at.should_not be_nil
32
+ <%= class_name %>.find(current_<%= file_name %>_id).remember_token.should_not be_nil
33
+ <%= class_name %>.find(current_<%= file_name %>_id).remember_token_expires_at.should_not be_nil
34
+ logout_killing_session!
35
+ <%= class_name %>.find(current_<%= file_name %>_id).remember_token.should be_nil
36
+ <%= class_name %>.find(current_<%= file_name %>_id).remember_token_expires_at.should be_nil
37
+ end
38
+ end
39
+
40
+ describe "logout_keeping_session!" do
41
+ before do
42
+ log_in
43
+ stub!(:reset_session)
44
+ end
45
+ it 'does not reset the session' do should_not_receive(:reset_session); logout_keeping_session! end
46
+ it 'kills my auth_token cookie' do should_receive(:kill_remember_cookie!); logout_keeping_session! end
47
+ it 'nils the current <%= file_name %>' do logout_keeping_session!; current_<%= file_name %>.should be_nil end
48
+ it 'kills :<%= file_name %>_id session' do
49
+ session.stub!(:[]=)
50
+ session.should_receive(:[]=).with(:<%= file_name %>_id, nil).at_least(:once)
51
+ logout_keeping_session!
52
+ end
53
+ it 'forgets me' do
54
+ current_<%= file_name %>_id = current_<%= file_name %>.id
55
+ current_<%= file_name %>.remember_me
56
+ current_<%= file_name %>.remember_token.should_not be_nil; current_<%= file_name %>.remember_token_expires_at.should_not be_nil
57
+ <%= class_name %>.find(current_<%= file_name %>_id).remember_token.should_not be_nil
58
+ <%= class_name %>.find(current_<%= file_name %>_id).remember_token_expires_at.should_not be_nil
59
+ logout_keeping_session!
60
+ <%= class_name %>.find(current_<%= file_name %>_id).remember_token.should be_nil
61
+ <%= class_name %>.find(current_<%= file_name %>_id).remember_token_expires_at.should be_nil
62
+ end
63
+ end
64
+
65
+ describe 'When logged out' do
66
+ it "should not be authorized?" do
67
+ authorized?().should be_false
68
+ end
69
+ end
70
+
71
+ #
72
+ # Cookie Login
73
+ #
74
+ describe "Logging in by cookie" do
75
+ def set_remember_token token, time
76
+ @<%= file_name %>[:remember_token] = token
77
+ @<%= file_name %>[:remember_token_expires_at] = time
78
+ @<%= file_name %>.save!
79
+ end
80
+ before do
81
+ @<%= file_name %> = <%= class_name %>.make
82
+ set_remember_token 'hello!', 5.minutes.from_now
83
+ end
84
+ it 'logs in with cookie' do
85
+ stub!(:cookies).and_return({ :auth_token => 'hello!' })
86
+ logged_in?.should be_true
87
+ end
88
+
89
+ it 'fails cookie login with bad cookie' do
90
+ should_receive(:cookies).at_least(:once).and_return({ :auth_token => 'i_haxxor_joo' })
91
+ logged_in?.should_not be_true
92
+ end
93
+
94
+ it 'fails cookie login with no cookie' do
95
+ set_remember_token nil, nil
96
+ should_receive(:cookies).at_least(:once).and_return({ })
97
+ logged_in?.should_not be_true
98
+ end
99
+
100
+ it 'fails expired cookie login' do
101
+ set_remember_token 'hello!', 5.minutes.ago
102
+ stub!(:cookies).and_return({ :auth_token => 'hello!' })
103
+ logged_in?.should_not be_true
104
+ end
105
+ end
106
+
107
+ end
@@ -0,0 +1,138 @@
1
+ require File.dirname(__FILE__) + '<%= ('/..'*controller_class_nesting_depth) + '/../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 <%= controller_class_name %>Controller do
8
+ before do
9
+ @<%= file_name %> = <%= class_name %>.make
10
+ @login_params = { :login => 'quentin', :password => 'test' }
11
+ <%= class_name %>.stub!(:authenticate).with(@login_params[:login], @login_params[:password]).and_return(@<%= file_name %>)
12
+ end
13
+ def do_create
14
+ post :create, @login_params
15
+ end
16
+ describe "on successful login," do
17
+ [ [:nil, nil, nil],
18
+ [:expired, 'valid_token', 15.minutes.ago],
19
+ [:different, 'i_haxxor_joo', 15.minutes.from_now],
20
+ [:valid, 'valid_token', 15.minutes.from_now]
21
+ ].each do |has_request_token, token_value, token_expiry|
22
+ [ true, false ].each do |want_remember_me|
23
+ describe "my request cookie token is #{has_request_token.to_s}," do
24
+ describe "and ask #{want_remember_me ? 'to' : 'not to'} be remembered" do
25
+ before do
26
+ @ccookies = mock('cookies')
27
+ controller.stub!(:cookies).and_return(@ccookies)
28
+ @ccookies.stub!(:[]).with(:auth_token).and_return(token_value)
29
+ @ccookies.stub!(:delete).with(:auth_token)
30
+ @ccookies.stub!(:[]=)
31
+ @<%= file_name %>.stub!(:remember_me)
32
+ @<%= file_name %>.stub!(:refresh_token)
33
+ @<%= file_name %>.stub!(:forget_me)
34
+ @<%= file_name %>.stub!(:remember_token).and_return(token_value)
35
+ @<%= file_name %>.stub!(:remember_token_expires_at).and_return(token_expiry)
36
+ @<%= file_name %>.stub!(:remember_token?).and_return(has_request_token == :valid)
37
+ if want_remember_me
38
+ @login_params[:remember_me] = '1'
39
+ else
40
+ @login_params[:remember_me] = '0'
41
+ end
42
+ end
43
+ it "kills existing login" do controller.should_receive(:logout_keeping_session!); do_create; end
44
+ it "authorizes me" do do_create; controller.send(:authorized?).should be_true; end
45
+ it "logs me in" do do_create; controller.send(:logged_in?).should be_true end
46
+ it "greets me nicely" do do_create; response.flash[:notice].should =~ /success/i end
47
+ it "sets/resets/expires cookie" do controller.should_receive(:handle_remember_cookie!).with(want_remember_me); do_create end
48
+ it "sends a cookie" do controller.should_receive(:send_remember_cookie!); do_create end
49
+ it 'redirects to the home page' do do_create; response.should redirect_to('/') end
50
+ 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
51
+ if (has_request_token == :valid)
52
+ it 'does not make new token' do @<%= file_name %>.should_not_receive(:remember_me); do_create end
53
+ it 'does refresh token' do @<%= file_name %>.should_receive(:refresh_token); do_create end
54
+ it "sets an auth cookie" do do_create; end
55
+ else
56
+ if want_remember_me
57
+ it 'makes a new token' do @<%= file_name %>.should_receive(:remember_me); do_create end
58
+ it "does not refresh token" do @<%= file_name %>.should_not_receive(:refresh_token); do_create end
59
+ it "sets an auth cookie" do do_create; end
60
+ else
61
+ it 'does not make new token' do @<%= file_name %>.should_not_receive(:remember_me); do_create end
62
+ it 'does not refresh token' do @<%= file_name %>.should_not_receive(:refresh_token); do_create end
63
+ it 'kills user token' do @<%= file_name %>.should_receive(:forget_me); do_create end
64
+ end
65
+ end
66
+ end # inner describe
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ describe "on failed login" do
73
+ before do
74
+ <%= class_name %>.should_receive(:authenticate).with(anything(), anything()).and_return(nil)
75
+ log_in
76
+ end
77
+ it 'logs out keeping session' do controller.should_receive(:logout_keeping_session!); do_create end
78
+ it 'flashes an error' do do_create; flash[:error].should =~ /Couldn't log you in as 'quentin'/ end
79
+ it 'renders the log in page' do do_create; response.should render_template('new') end
80
+ it "doesn't log me in" do do_create; controller.send(:logged_in?).should == false end
81
+ it "doesn't send password back" do
82
+ @login_params[:password] = 'FROBNOZZ'
83
+ do_create
84
+ response.should_not have_text(/FROBNOZZ/i)
85
+ end
86
+ end
87
+
88
+ describe "on signout" do
89
+ def do_destroy
90
+ get :destroy
91
+ end
92
+ before do
93
+ log_in
94
+ end
95
+ it 'logs me out' do controller.should_receive(:logout_killing_session!); do_destroy end
96
+ it 'redirects me to the home page' do do_destroy; response.should be_redirect end
97
+ end
98
+
99
+ end
100
+
101
+ describe <%= controller_class_name %>Controller do
102
+ describe "route generation" do
103
+ it "should route the new <%= controller_controller_name %> action correctly" do
104
+ route_for(:controller => '<%= controller_controller_name %>', :action => 'new').should == "/login"
105
+ end
106
+ it "should route the create <%= controller_controller_name %> correctly" do
107
+ route_for(:controller => '<%= controller_controller_name %>', :action => 'create').should == { :path => "/<%= controller_routing_path %>", :method => :post }
108
+ end
109
+ it "should route the destroy <%= controller_controller_name %> action correctly" do
110
+ route_for(:controller => '<%= controller_controller_name %>', :action => 'destroy').should == "/logout"
111
+ end
112
+ end
113
+
114
+ describe "route recognition" do
115
+ it "should generate params from GET /login correctly" do
116
+ params_from(:get, '/login').should == {:controller => '<%= controller_controller_name %>', :action => 'new'}
117
+ end
118
+ it "should generate params from POST /<%= controller_routing_path %> correctly" do
119
+ params_from(:post, '/<%= controller_routing_path %>').should == {:controller => '<%= controller_controller_name %>', :action => 'create'}
120
+ end
121
+ it "should generate params from DELETE /<%= controller_routing_path %> correctly" do
122
+ params_from(:delete, '/logout').should == {:controller => '<%= controller_controller_name %>', :action => 'destroy'}
123
+ end
124
+ end
125
+
126
+ describe "named routing" do
127
+ before(:each) do
128
+ get :new
129
+ end
130
+ it "should route <%= controller_routing_name %>_path() correctly" do
131
+ <%= controller_routing_name %>_path().should == "/<%= controller_routing_path %>"
132
+ end
133
+ it "should route new_<%= controller_routing_name %>_path() correctly" do
134
+ new_<%= controller_routing_name %>_path().should == "/<%= controller_routing_path %>/new"
135
+ end
136
+ end
137
+
138
+ end
@@ -0,0 +1,197 @@
1
+ require File.dirname(__FILE__) + '<%= ('/..'*model_controller_class_nesting_depth) + '/../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 <%= model_controller_class_name %>Controller do
8
+ it 'allows signup' do
9
+ lambda do
10
+ create_<%= file_name %>
11
+ response.should be_redirect
12
+ end.should change(<%= class_name %>, :count).by(1)
13
+ end
14
+
15
+ <% if options[:stateful] %>
16
+ it 'signs up user in pending state' do
17
+ create_<%= file_name %>
18
+ assigns(:<%= file_name %>).reload
19
+ assigns(:<%= file_name %>).should be_pending
20
+ end<% end %>
21
+
22
+ <% if options[:include_activation] -%>
23
+ it 'signs up user with activation code' do
24
+ create_<%= file_name %>
25
+ assigns(:<%= file_name %>).reload
26
+ assigns(:<%= file_name %>).activation_code.should_not be_nil
27
+ end<% end -%>
28
+
29
+ it 'requires login on signup' do
30
+ lambda do
31
+ create_<%= file_name %>(:login => nil)
32
+ assigns[:<%= file_name %>].errors.on(:login).should_not be_nil
33
+ response.should be_success
34
+ end.should_not change(<%= class_name %>, :count)
35
+ end
36
+
37
+ it 'requires password on signup' do
38
+ lambda do
39
+ create_<%= file_name %>(:password => nil)
40
+ assigns[:<%= file_name %>].errors.on(:password).should_not be_nil
41
+ response.should be_success
42
+ end.should_not change(<%= class_name %>, :count)
43
+ end
44
+
45
+ it 'requires password confirmation on signup' do
46
+ lambda do
47
+ create_<%= file_name %>(:password_confirmation => nil)
48
+ assigns[:<%= file_name %>].errors.on(:password_confirmation).should_not be_nil
49
+ response.should be_success
50
+ end.should_not change(<%= class_name %>, :count)
51
+ end
52
+
53
+ it 'requires email on signup' do
54
+ lambda do
55
+ create_<%= file_name %>(:email => nil)
56
+ assigns[:<%= file_name %>].errors.on(:email).should_not be_nil
57
+ response.should be_success
58
+ end.should_not change(<%= class_name %>, :count)
59
+ end
60
+
61
+ <% if options[:include_activation] %>
62
+ it 'activates user' do
63
+ create_<%= file_name %>(:login => 'aaron', :password => 'monkey', :password_confirmation => 'monkey')
64
+ <%= class_name %>.authenticate('aaron', 'monkey').should be_nil
65
+ get :activate, :activation_code => assigns[:<%= file_name %>].activation_code
66
+ response.should redirect_to('/login')
67
+ flash[:notice].should_not be_nil
68
+ flash[:error ].should be_nil
69
+ <%= class_name %>.authenticate('aaron', 'monkey').should == assigns[:<%= file_name %>]
70
+ end
71
+
72
+ it 'does not activate user without key' do
73
+ get :activate
74
+ flash[:notice].should be_nil
75
+ flash[:error ].should_not be_nil
76
+ end
77
+
78
+ it 'does not activate user with blank key' do
79
+ get :activate, :activation_code => ''
80
+ flash[:notice].should be_nil
81
+ flash[:error ].should_not be_nil
82
+ end
83
+
84
+ it 'does not activate user with bogus key' do
85
+ get :activate, :activation_code => 'i_haxxor_joo'
86
+ flash[:notice].should be_nil
87
+ flash[:error ].should_not be_nil
88
+ end<% end %>
89
+
90
+ def create_<%= file_name %>(options = {})
91
+ post :create, :<%= file_name %> => { :login => 'quire', :email => 'quire@example.com',
92
+ :password => 'quire69', :password_confirmation => 'quire69' }.merge(options)
93
+ end
94
+ end
95
+
96
+ describe <%= model_controller_class_name %>Controller do
97
+ describe "route generation" do
98
+ it "should route <%= model_controller_controller_name %>'s 'index' action correctly" do
99
+ route_for(:controller => '<%= model_controller_controller_name %>', :action => 'index').should == "/<%= model_controller_routing_path %>"
100
+ end
101
+
102
+ it "should route <%= model_controller_controller_name %>'s 'new' action correctly" do
103
+ route_for(:controller => '<%= model_controller_controller_name %>', :action => 'new').should == "/signup"
104
+ end
105
+
106
+ it "should route {:controller => '<%= model_controller_controller_name %>', :action => 'create'} correctly" do
107
+ route_for(:controller => '<%= model_controller_controller_name %>', :action => 'create').should == "/register"
108
+ end
109
+
110
+ it "should route <%= model_controller_controller_name %>'s 'show' action correctly" do
111
+ route_for(:controller => '<%= model_controller_controller_name %>', :action => 'show', :id => '1').should == "/<%= model_controller_routing_path %>/1"
112
+ end
113
+
114
+ it "should route <%= model_controller_controller_name %>'s 'edit' action correctly" do
115
+ route_for(:controller => '<%= model_controller_controller_name %>', :action => 'edit', :id => '1').should == "/<%= model_controller_routing_path %>/1/edit"
116
+ end
117
+
118
+ it "should route <%= model_controller_controller_name %>'s 'update' action correctly" do
119
+ route_for(:controller => '<%= model_controller_controller_name %>', :action => 'update', :id => '1').should == { :path => "/<%= model_controller_routing_path %>/1", :method => :put }
120
+ end
121
+
122
+ it "should route <%= model_controller_controller_name %>'s 'destroy' action correctly" do
123
+ route_for(:controller => '<%= model_controller_controller_name %>', :action => 'destroy', :id => '1').should == { :path => "/<%= model_controller_routing_path %>/1", :method => :delete }
124
+ end
125
+ end
126
+
127
+ describe "route recognition" do
128
+ it "should generate params for <%= model_controller_controller_name %>'s index action from GET /<%= model_controller_routing_path %>" do
129
+ params_from(:get, '/<%= model_controller_routing_path %>').should == {:controller => '<%= model_controller_controller_name %>', :action => 'index'}
130
+ params_from(:get, '/<%= model_controller_routing_path %>.xml').should == {:controller => '<%= model_controller_controller_name %>', :action => 'index', :format => 'xml'}
131
+ params_from(:get, '/<%= model_controller_routing_path %>.json').should == {:controller => '<%= model_controller_controller_name %>', :action => 'index', :format => 'json'}
132
+ end
133
+
134
+ it "should generate params for <%= model_controller_controller_name %>'s new action from GET /<%= model_controller_routing_path %>" do
135
+ params_from(:get, '/<%= model_controller_routing_path %>/new').should == {:controller => '<%= model_controller_controller_name %>', :action => 'new'}
136
+ params_from(:get, '/<%= model_controller_routing_path %>/new.xml').should == {:controller => '<%= model_controller_controller_name %>', :action => 'new', :format => 'xml'}
137
+ params_from(:get, '/<%= model_controller_routing_path %>/new.json').should == {:controller => '<%= model_controller_controller_name %>', :action => 'new', :format => 'json'}
138
+ end
139
+
140
+ it "should generate params for <%= model_controller_controller_name %>'s create action from POST /<%= model_controller_routing_path %>" do
141
+ params_from(:post, '/<%= model_controller_routing_path %>').should == {:controller => '<%= model_controller_controller_name %>', :action => 'create'}
142
+ params_from(:post, '/<%= model_controller_routing_path %>.xml').should == {:controller => '<%= model_controller_controller_name %>', :action => 'create', :format => 'xml'}
143
+ params_from(:post, '/<%= model_controller_routing_path %>.json').should == {:controller => '<%= model_controller_controller_name %>', :action => 'create', :format => 'json'}
144
+ end
145
+
146
+ it "should generate params for <%= model_controller_controller_name %>'s show action from GET /<%= model_controller_routing_path %>/1" do
147
+ params_from(:get , '/<%= model_controller_routing_path %>/1').should == {:controller => '<%= model_controller_controller_name %>', :action => 'show', :id => '1'}
148
+ params_from(:get , '/<%= model_controller_routing_path %>/1.xml').should == {:controller => '<%= model_controller_controller_name %>', :action => 'show', :id => '1', :format => 'xml'}
149
+ params_from(:get , '/<%= model_controller_routing_path %>/1.json').should == {:controller => '<%= model_controller_controller_name %>', :action => 'show', :id => '1', :format => 'json'}
150
+ end
151
+
152
+ it "should generate params for <%= model_controller_controller_name %>'s edit action from GET /<%= model_controller_routing_path %>/1/edit" do
153
+ params_from(:get , '/<%= model_controller_routing_path %>/1/edit').should == {:controller => '<%= model_controller_controller_name %>', :action => 'edit', :id => '1'}
154
+ end
155
+
156
+ it "should generate params {:controller => '<%= model_controller_controller_name %>', :action => update', :id => '1'} from PUT /<%= model_controller_routing_path %>/1" do
157
+ params_from(:put , '/<%= model_controller_routing_path %>/1').should == {:controller => '<%= model_controller_controller_name %>', :action => 'update', :id => '1'}
158
+ params_from(:put , '/<%= model_controller_routing_path %>/1.xml').should == {:controller => '<%= model_controller_controller_name %>', :action => 'update', :id => '1', :format => 'xml'}
159
+ params_from(:put , '/<%= model_controller_routing_path %>/1.json').should == {:controller => '<%= model_controller_controller_name %>', :action => 'update', :id => '1', :format => 'json'}
160
+ end
161
+
162
+ it "should generate params for <%= model_controller_controller_name %>'s destroy action from DELETE /<%= model_controller_routing_path %>/1" do
163
+ params_from(:delete, '/<%= model_controller_routing_path %>/1').should == {:controller => '<%= model_controller_controller_name %>', :action => 'destroy', :id => '1'}
164
+ params_from(:delete, '/<%= model_controller_routing_path %>/1.xml').should == {:controller => '<%= model_controller_controller_name %>', :action => 'destroy', :id => '1', :format => 'xml'}
165
+ params_from(:delete, '/<%= model_controller_routing_path %>/1.json').should == {:controller => '<%= model_controller_controller_name %>', :action => 'destroy', :id => '1', :format => 'json'}
166
+ end
167
+ end
168
+
169
+ describe "named routing" do
170
+ before(:each) do
171
+ get :new
172
+ end
173
+
174
+ it "should route <%= model_controller_routing_name %>_path() to /<%= model_controller_routing_path %>" do
175
+ <%= model_controller_routing_name %>_path().should == "/<%= model_controller_routing_path %>"
176
+ <%= model_controller_routing_name %>_path(:format => 'xml').should == "/<%= model_controller_routing_path %>.xml"
177
+ <%= model_controller_routing_name %>_path(:format => 'json').should == "/<%= model_controller_routing_path %>.json"
178
+ end
179
+
180
+ it "should route new_<%= model_controller_routing_name.singularize %>_path() to /<%= model_controller_routing_path %>/new" do
181
+ new_<%= model_controller_routing_name.singularize %>_path().should == "/<%= model_controller_routing_path %>/new"
182
+ new_<%= model_controller_routing_name.singularize %>_path(:format => 'xml').should == "/<%= model_controller_routing_path %>/new.xml"
183
+ new_<%= model_controller_routing_name.singularize %>_path(:format => 'json').should == "/<%= model_controller_routing_path %>/new.json"
184
+ end
185
+
186
+ it "should route <%= model_controller_routing_name.singularize %>_(:id => '1') to /<%= model_controller_routing_path %>/1" do
187
+ <%= model_controller_routing_name.singularize %>_path(:id => '1').should == "/<%= model_controller_routing_path %>/1"
188
+ <%= model_controller_routing_name.singularize %>_path(:id => '1', :format => 'xml').should == "/<%= model_controller_routing_path %>/1.xml"
189
+ <%= model_controller_routing_name.singularize %>_path(:id => '1', :format => 'json').should == "/<%= model_controller_routing_path %>/1.json"
190
+ end
191
+
192
+ it "should route edit_<%= model_controller_routing_name.singularize %>_path(:id => '1') to /<%= model_controller_routing_path %>/1/edit" do
193
+ edit_<%= model_controller_routing_name.singularize %>_path(:id => '1').should == "/<%= model_controller_routing_path %>/1/edit"
194
+ end
195
+ end
196
+
197
+ end