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,82 @@
1
+ require 'test_helper'
2
+ require '<%= controller_file_name %>_controller'
3
+
4
+ # Re-raise errors caught by the controller.
5
+ class <%= controller_class_name %>Controller; def rescue_action(e) raise e end; end
6
+
7
+ class <%= controller_class_name %>ControllerTest < ActionController::TestCase
8
+ # Be sure to include AuthenticatedTestHelper in test/test_helper.rb instead
9
+ # Then, you can remove it from this and the units test.
10
+ include AuthenticatedTestHelper
11
+
12
+ fixtures :<%= table_name %>
13
+
14
+ def test_should_login_and_redirect
15
+ post :create, :login => 'quentin', :password => 'monkey'
16
+ assert session[:<%= file_name %>_id]
17
+ assert_response :redirect
18
+ end
19
+
20
+ def test_should_fail_login_and_not_redirect
21
+ post :create, :login => 'quentin', :password => 'bad password'
22
+ assert_nil session[:<%= file_name %>_id]
23
+ assert_response :success
24
+ end
25
+
26
+ def test_should_logout
27
+ login_as :quentin
28
+ get :destroy
29
+ assert_nil session[:<%= file_name %>_id]
30
+ assert_response :redirect
31
+ end
32
+
33
+ def test_should_remember_me
34
+ @request.cookies["auth_token"] = nil
35
+ post :create, :login => 'quentin', :password => 'monkey', :remember_me => "1"
36
+ assert_not_nil @response.cookies["auth_token"]
37
+ end
38
+
39
+ def test_should_not_remember_me
40
+ @request.cookies["auth_token"] = nil
41
+ post :create, :login => 'quentin', :password => 'monkey', :remember_me => "0"
42
+ puts @response.cookies["auth_token"]
43
+ assert @response.cookies["auth_token"].blank?
44
+ end
45
+
46
+ def test_should_delete_token_on_logout
47
+ login_as :quentin
48
+ get :destroy
49
+ assert @response.cookies["auth_token"].blank?
50
+ end
51
+
52
+ def test_should_login_with_cookie
53
+ <%= table_name %>(:quentin).remember_me
54
+ @request.cookies["auth_token"] = cookie_for(:quentin)
55
+ get :new
56
+ assert @controller.send(:logged_in?)
57
+ end
58
+
59
+ def test_should_fail_expired_cookie_login
60
+ <%= table_name %>(:quentin).remember_me
61
+ <%= table_name %>(:quentin).update_attribute :remember_token_expires_at, 5.minutes.ago
62
+ @request.cookies["auth_token"] = cookie_for(:quentin)
63
+ get :new
64
+ assert !@controller.send(:logged_in?)
65
+ end
66
+
67
+ def test_should_fail_cookie_login
68
+ <%= table_name %>(:quentin).remember_me
69
+ @request.cookies["auth_token"] = auth_token('invalid_auth_token')
70
+ get :new
71
+ assert !@controller.send(:logged_in?)
72
+ end
73
+
74
+ protected
75
+ def auth_token(token)
76
+ CGI::Cookie.new('name' => 'auth_token', 'value' => token)
77
+ end
78
+
79
+ def cookie_for(<%= file_name %>)
80
+ auth_token <%= table_name %>(<%= file_name %>).remember_token
81
+ end
82
+ end
@@ -0,0 +1,32 @@
1
+ require 'test_helper'
2
+ require '<%= file_name %>_mailer'
3
+
4
+ class <%= class_name %>MailerTest < ActionMailer::TestCase
5
+
6
+ def setup
7
+ @<%= file_name %> = <%= table_name %>(:quentin)
8
+ end
9
+
10
+
11
+ test "signup_notification" do
12
+ # Send the email, then test that it got queued
13
+ email = UserMailer.signup_notification(@<%= file_name %>).deliver
14
+ assert !ActionMailer::Base.deliveries.empty?
15
+
16
+ assert_equal [@<%= file_name %>.email], email.to
17
+ assert_equal "[YOURSITE] Please activate your new account", email.subject
18
+ assert_match /Your account has been created./, email.encoded
19
+ assert_match /Visit this url to activate your account/, email.encoded
20
+ end
21
+
22
+ test "activation" do
23
+ email = UserMailer.activation(@<%= file_name %>).deliver
24
+ assert !ActionMailer::Base.deliveries.empty?
25
+
26
+ assert_equal [@<%= file_name %>.email], email.to
27
+ assert_equal "[YOURSITE] Your account has been activated!", email.subject
28
+ assert_match /your account has been activated. Welcome aboard!/, email.encoded
29
+ assert_match /http\:\/\/YOURSITE\//, email.encoded
30
+ end
31
+
32
+ end
@@ -0,0 +1,93 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ require '<%= model_controller_file_name %>_controller'
3
+
4
+ # Re-raise errors caught by the controller.
5
+ class <%= model_controller_class_name %>Controller; def rescue_action(e) raise e end; end
6
+
7
+ class <%= model_controller_class_name %>ControllerTest < ActionController::TestCase
8
+ # Be sure to include AuthenticatedTestHelper in test/test_helper.rb instead
9
+ # Then, you can remove it from this and the units test.
10
+ include AuthenticatedTestHelper
11
+
12
+ fixtures :<%= table_name %>
13
+
14
+ def test_should_allow_signup
15
+ assert_difference '<%= class_name %>.count' do
16
+ create_<%= file_name %>
17
+ assert_response :redirect
18
+ end
19
+ end
20
+
21
+ def test_should_require_login_on_signup
22
+ assert_no_difference '<%= class_name %>.count' do
23
+ create_<%= file_name %>(:login => nil)
24
+ assert assigns(:<%= file_name %>).errors.on(:login)
25
+ assert_response :success
26
+ end
27
+ end
28
+
29
+ def test_should_require_password_on_signup
30
+ assert_no_difference '<%= class_name %>.count' do
31
+ create_<%= file_name %>(:password => nil)
32
+ assert assigns(:<%= file_name %>).errors.on(:password)
33
+ assert_response :success
34
+ end
35
+ end
36
+
37
+ def test_should_require_password_confirmation_on_signup
38
+ assert_no_difference '<%= class_name %>.count' do
39
+ create_<%= file_name %>(:password_confirmation => nil)
40
+ assert assigns(:<%= file_name %>).errors.on(:password_confirmation)
41
+ assert_response :success
42
+ end
43
+ end
44
+
45
+ def test_should_require_email_on_signup
46
+ assert_no_difference '<%= class_name %>.count' do
47
+ create_<%= file_name %>(:email => nil)
48
+ assert assigns(:<%= file_name %>).errors.on(:email)
49
+ assert_response :success
50
+ end
51
+ end
52
+ <% if options[:stateful] %>
53
+ def test_should_sign_up_user_in_pending_state
54
+ create_<%= file_name %>
55
+ assigns(:<%= file_name %>).reload
56
+ assert assigns(:<%= file_name %>).pending?
57
+ end<% end %>
58
+
59
+ <% if options[:include_activation] %>
60
+ def test_should_sign_up_user_with_activation_code
61
+ create_<%= file_name %>
62
+ assigns(:<%= file_name %>).reload
63
+ assert_not_nil assigns(:<%= file_name %>).activation_code
64
+ end
65
+
66
+ def test_should_activate_user
67
+ assert_nil <%= class_name %>.authenticate('aaron', 'test')
68
+ get :activate, :activation_code => <%= table_name %>(:aaron).activation_code
69
+ assert_redirected_to '/login'
70
+ assert_not_nil flash[:notice]
71
+ assert_equal <%= table_name %>(:aaron), <%= class_name %>.authenticate('aaron', 'monkey')
72
+ end
73
+
74
+ def test_should_not_activate_user_without_key
75
+ get :activate
76
+ assert_nil flash[:notice]
77
+ rescue ActionController::RoutingError
78
+ # in the event your routes deny this, we'll just bow out gracefully.
79
+ end
80
+
81
+ def test_should_not_activate_user_with_blank_key
82
+ get :activate, :activation_code => ''
83
+ assert_nil flash[:notice]
84
+ rescue ActionController::RoutingError
85
+ # well played, sir
86
+ end<% end %>
87
+
88
+ protected
89
+ def create_<%= file_name %>(options = {})
90
+ post :create, :<%= file_name %> => { :login => 'quire', :email => 'quire@example.com',
91
+ :password => 'quire69', :password_confirmation => 'quire69' }.merge(options)
92
+ end
93
+ end
@@ -0,0 +1,164 @@
1
+ require 'test_helper'
2
+
3
+ class <%= class_name %>Test < ActiveSupport::TestCase
4
+ # Be sure to include AuthenticatedTestHelper in test/test_helper.rb instead.
5
+ # Then, you can remove it from this and the functional test.
6
+ include AuthenticatedTestHelper
7
+ fixtures :<%= table_name %>
8
+
9
+ def test_should_create_<%= file_name %>
10
+ assert_difference '<%= class_name %>.count' do
11
+ <%= file_name %> = create_<%= file_name %>
12
+ assert !<%= file_name %>.new_record?, "#{<%= file_name %>.errors.full_messages.to_sentence}"
13
+ end
14
+ end
15
+ <% if options[:include_activation] %>
16
+ def test_should_initialize_activation_code_upon_creation
17
+ <%= file_name %> = create_<%= file_name %>
18
+ <%= file_name %>.reload
19
+ assert_not_nil <%= file_name %>.activation_code
20
+ end
21
+ <% end %><% if options[:stateful] %>
22
+ def test_should_create_and_start_in_pending_state
23
+ <%= file_name %> = create_<%= file_name %>
24
+ <%= file_name %>.reload
25
+ assert <%= file_name %>.pending?
26
+ end
27
+
28
+ <% end %>
29
+ def test_should_require_login
30
+ assert_no_difference '<%= class_name %>.count' do
31
+ u = create_<%= file_name %>(:login => nil)
32
+ assert u.errors.on(:login)
33
+ end
34
+ end
35
+
36
+ def test_should_require_password
37
+ assert_no_difference '<%= class_name %>.count' do
38
+ u = create_<%= file_name %>(:password => nil)
39
+ assert u.errors.on(:password)
40
+ end
41
+ end
42
+
43
+ def test_should_require_password_confirmation
44
+ assert_no_difference '<%= class_name %>.count' do
45
+ u = create_<%= file_name %>(:password_confirmation => nil)
46
+ assert u.errors.on(:password_confirmation)
47
+ end
48
+ end
49
+
50
+ def test_should_require_email
51
+ assert_no_difference '<%= class_name %>.count' do
52
+ u = create_<%= file_name %>(:email => nil)
53
+ assert u.errors.on(:email)
54
+ end
55
+ end
56
+
57
+ def test_should_reset_password
58
+ <%= table_name %>(:quentin).update_attributes(:password => 'new password', :password_confirmation => 'new password')
59
+ assert_equal <%= table_name %>(:quentin), <%= class_name %>.authenticate('quentin', 'new password')
60
+ end
61
+
62
+ def test_should_not_rehash_password
63
+ <%= table_name %>(:quentin).update_attributes(:login => 'quentin2')
64
+ assert_equal <%= table_name %>(:quentin), <%= class_name %>.authenticate('quentin2', 'monkey')
65
+ end
66
+
67
+ def test_should_authenticate_<%= file_name %>
68
+ assert_equal <%= table_name %>(:quentin), <%= class_name %>.authenticate('quentin', 'monkey')
69
+ end
70
+
71
+ def test_should_set_remember_token
72
+ <%= table_name %>(:quentin).remember_me
73
+ assert_not_nil <%= table_name %>(:quentin).remember_token
74
+ assert_not_nil <%= table_name %>(:quentin).remember_token_expires_at
75
+ end
76
+
77
+ def test_should_unset_remember_token
78
+ <%= table_name %>(:quentin).remember_me
79
+ assert_not_nil <%= table_name %>(:quentin).remember_token
80
+ <%= table_name %>(:quentin).forget_me
81
+ assert_nil <%= table_name %>(:quentin).remember_token
82
+ end
83
+
84
+ def test_should_remember_me_for_one_week
85
+ before = 1.week.from_now.utc
86
+ <%= table_name %>(:quentin).remember_me_for 1.week
87
+ after = 1.week.from_now.utc
88
+ assert_not_nil <%= table_name %>(:quentin).remember_token
89
+ assert_not_nil <%= table_name %>(:quentin).remember_token_expires_at
90
+ assert <%= table_name %>(:quentin).remember_token_expires_at.between?(before, after)
91
+ end
92
+
93
+ def test_should_remember_me_until_one_week
94
+ time = 1.week.from_now.utc
95
+ <%= table_name %>(:quentin).remember_me_until time
96
+ assert_not_nil <%= table_name %>(:quentin).remember_token
97
+ assert_not_nil <%= table_name %>(:quentin).remember_token_expires_at
98
+ assert_equal <%= table_name %>(:quentin).remember_token_expires_at, time
99
+ end
100
+
101
+ def test_should_remember_me_default_two_weeks
102
+ before = 2.weeks.from_now.utc
103
+ <%= table_name %>(:quentin).remember_me
104
+ after = 2.weeks.from_now.utc
105
+ assert_not_nil <%= table_name %>(:quentin).remember_token
106
+ assert_not_nil <%= table_name %>(:quentin).remember_token_expires_at
107
+ assert <%= table_name %>(:quentin).remember_token_expires_at.between?(before, after)
108
+ end
109
+ <% if options[:stateful] %>
110
+ def test_should_register_passive_<%= file_name %>
111
+ <%= file_name %> = create_<%= file_name %>(:password => nil, :password_confirmation => nil)
112
+ assert <%= file_name %>.passive?
113
+ <%= file_name %>.update_attributes(:password => 'new password', :password_confirmation => 'new password')
114
+ <%= file_name %>.register!
115
+ assert <%= file_name %>.pending?
116
+ end
117
+
118
+ def test_should_suspend_<%= file_name %>
119
+ <%= table_name %>(:quentin).suspend!
120
+ assert <%= table_name %>(:quentin).suspended?
121
+ end
122
+
123
+ def test_suspended_<%= file_name %>_should_not_authenticate
124
+ <%= table_name %>(:quentin).suspend!
125
+ assert_not_equal <%= table_name %>(:quentin), <%= class_name %>.authenticate('quentin', 'test')
126
+ end
127
+
128
+ def test_should_unsuspend_<%= file_name %>_to_active_state
129
+ <%= table_name %>(:quentin).suspend!
130
+ assert <%= table_name %>(:quentin).suspended?
131
+ <%= table_name %>(:quentin).unsuspend!
132
+ assert <%= table_name %>(:quentin).active?
133
+ end
134
+
135
+ def test_should_unsuspend_<%= file_name %>_with_nil_activation_code_and_activated_at_to_passive_state
136
+ <%= table_name %>(:quentin).suspend!
137
+ <%= class_name %>.update_all :activation_code => nil, :activated_at => nil
138
+ assert <%= table_name %>(:quentin).suspended?
139
+ <%= table_name %>(:quentin).reload.unsuspend!
140
+ assert <%= table_name %>(:quentin).passive?
141
+ end
142
+
143
+ def test_should_unsuspend_<%= file_name %>_with_activation_code_and_nil_activated_at_to_pending_state
144
+ <%= table_name %>(:quentin).suspend!
145
+ <%= class_name %>.update_all :activation_code => 'foo-bar', :activated_at => nil
146
+ assert <%= table_name %>(:quentin).suspended?
147
+ <%= table_name %>(:quentin).reload.unsuspend!
148
+ assert <%= table_name %>(:quentin).pending?
149
+ end
150
+
151
+ def test_should_delete_<%= file_name %>
152
+ assert_nil <%= table_name %>(:quentin).deleted_at
153
+ <%= table_name %>(:quentin).delete!
154
+ assert_not_nil <%= table_name %>(:quentin).deleted_at
155
+ assert <%= table_name %>(:quentin).deleted?
156
+ end
157
+ <% end %>
158
+ protected
159
+ def create_<%= file_name %>(options = {})
160
+ record = <%= class_name %>.new({ :login => 'quire', :email => 'quire@example.com', :password => 'quire69', :password_confirmation => 'quire69' }.merge(options))
161
+ record.<% if options[:stateful] %>register! if record.valid?<% else %>save<% end %>
162
+ record
163
+ end
164
+ end
@@ -0,0 +1,3 @@
1
+ require "authentication"
2
+ require "authentication/by_password"
3
+ require "authentication/by_cookie_token"
@@ -0,0 +1,33 @@
1
+ require 'digest/sha1'
2
+ require 'erb'
3
+
4
+ def site_keys_file
5
+ File.join("config", "initializers", "site_keys.rb")
6
+ end
7
+
8
+ def secure_digest(*args)
9
+ Digest::SHA1.hexdigest(args.flatten.join('--'))
10
+ end
11
+
12
+ def make_token
13
+ secure_digest(Time.now, (1..10).map{ rand.to_s })
14
+ end
15
+
16
+ def make_site_keys_rb
17
+ site_key = secure_digest(Time.now, (1..10).map{ rand.to_s })
18
+ site_key_erb = <<-EOF
19
+ # key of 40 chars length
20
+ REST_AUTH_SITE_KEY = '#{site_key}'
21
+ REST_AUTH_DIGEST_STRETCHES = 10
22
+ EOF
23
+ end
24
+
25
+ namespace :auth do
26
+ namespace :gen do
27
+ desc "Generates config/initializers/site_keys.rb"
28
+ task :site_key do
29
+ file = ENV['file'] || site_keys_file
30
+ File.open(file, "w"){|f| f.write(make_site_keys_rb)}
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ module Trustification
2
+ def self.included(recipient)
3
+ recipient.extend(ModelClassMethods)
4
+ recipient.class_eval do
5
+ include ModelInstanceMethods
6
+ end
7
+ end
8
+
9
+ module ModelClassMethods
10
+ end # class methods
11
+
12
+ module ModelInstanceMethods
13
+ end # instance methods
14
+ end
@@ -0,0 +1,20 @@
1
+ module Trustification
2
+ module EmailValidation
3
+ unless Object.constants.include? "CONSTANTS_DEFINED"
4
+ CONSTANTS_DEFINED = true # sorry for the C idiom
5
+ end
6
+
7
+ def self.included(recipient)
8
+ recipient.extend(ClassMethods)
9
+ recipient.class_eval do
10
+ include InstanceMethods
11
+ end
12
+ end
13
+
14
+ module ClassMethods
15
+ end # class methods
16
+
17
+ module InstanceMethods
18
+ end # instance methods
19
+ end
20
+ end