kellyfelkins-clearance 0.5.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/CHANGELOG.textile +84 -0
  2. data/LICENSE +21 -0
  3. data/README.textile +76 -0
  4. data/Rakefile +73 -0
  5. data/generators/clearance/USAGE +1 -0
  6. data/generators/clearance/clearance_generator.rb +96 -0
  7. data/generators/clearance/lib/insert_commands.rb +103 -0
  8. data/generators/clearance/lib/rake_commands.rb +22 -0
  9. data/generators/clearance/templates/README +45 -0
  10. data/generators/clearance/templates/app/controllers/application.rb +5 -0
  11. data/generators/clearance/templates/app/controllers/confirmations_controller.rb +3 -0
  12. data/generators/clearance/templates/app/controllers/passwords_controller.rb +3 -0
  13. data/generators/clearance/templates/app/controllers/sessions_controller.rb +3 -0
  14. data/generators/clearance/templates/app/controllers/users_controller.rb +3 -0
  15. data/generators/clearance/templates/app/models/clearance_mailer.rb +5 -0
  16. data/generators/clearance/templates/app/models/user.rb +3 -0
  17. data/generators/clearance/templates/app/views/clearance_mailer/change_password.html.erb +7 -0
  18. data/generators/clearance/templates/app/views/clearance_mailer/confirmation.html.erb +2 -0
  19. data/generators/clearance/templates/app/views/passwords/edit.html.erb +23 -0
  20. data/generators/clearance/templates/app/views/passwords/new.html.erb +15 -0
  21. data/generators/clearance/templates/app/views/sessions/new.html.erb +28 -0
  22. data/generators/clearance/templates/app/views/users/_form.html.erb +13 -0
  23. data/generators/clearance/templates/app/views/users/edit.html.erb +6 -0
  24. data/generators/clearance/templates/app/views/users/new.html.erb +6 -0
  25. data/generators/clearance/templates/db/migrate/create_users_with_clearance_columns.rb +20 -0
  26. data/generators/clearance/templates/db/migrate/update_users_with_clearance_columns.rb +41 -0
  27. data/generators/clearance/templates/test/factories/clearance.rb +16 -0
  28. data/generators/clearance/templates/test/functional/confirmations_controller_test.rb +5 -0
  29. data/generators/clearance/templates/test/functional/passwords_controller_test.rb +5 -0
  30. data/generators/clearance/templates/test/functional/sessions_controller_test.rb +5 -0
  31. data/generators/clearance/templates/test/functional/users_controller_test.rb +5 -0
  32. data/generators/clearance/templates/test/unit/clearance_mailer_test.rb +6 -0
  33. data/generators/clearance/templates/test/unit/user_test.rb +5 -0
  34. data/generators/clearance_features/USAGE +1 -0
  35. data/generators/clearance_features/clearance_features_generator.rb +20 -0
  36. data/generators/clearance_features/templates/features/password_reset.feature +31 -0
  37. data/generators/clearance_features/templates/features/sign_in.feature +41 -0
  38. data/generators/clearance_features/templates/features/sign_out.feature +22 -0
  39. data/generators/clearance_features/templates/features/sign_up.feature +30 -0
  40. data/generators/clearance_features/templates/features/step_definitions/clearance_steps.rb +110 -0
  41. data/generators/clearance_features/templates/features/step_definitions/factory_girl_steps.rb +5 -0
  42. data/generators/clearance_features/templates/features/support/paths.rb +25 -0
  43. data/lib/clearance.rb +15 -0
  44. data/lib/clearance/app/controllers/application_controller.rb +84 -0
  45. data/lib/clearance/app/controllers/confirmations_controller.rb +63 -0
  46. data/lib/clearance/app/controllers/passwords_controller.rb +79 -0
  47. data/lib/clearance/app/controllers/sessions_controller.rb +74 -0
  48. data/lib/clearance/app/controllers/users_controller.rb +45 -0
  49. data/lib/clearance/app/models/clearance_mailer.rb +23 -0
  50. data/lib/clearance/app/models/user.rb +119 -0
  51. data/lib/clearance/lib/extensions/errors.rb +4 -0
  52. data/lib/clearance/lib/extensions/rescue.rb +1 -0
  53. data/lib/clearance/test/functional/confirmations_controller_test.rb +72 -0
  54. data/lib/clearance/test/functional/passwords_controller_test.rb +180 -0
  55. data/lib/clearance/test/functional/sessions_controller_test.rb +187 -0
  56. data/lib/clearance/test/functional/users_controller_test.rb +60 -0
  57. data/lib/clearance/test/unit/clearance_mailer_test.rb +65 -0
  58. data/lib/clearance/test/unit/user_test.rb +243 -0
  59. data/rails/init.rb +1 -0
  60. data/shoulda_macros/clearance.rb +241 -0
  61. metadata +157 -0
@@ -0,0 +1,187 @@
1
+ module Clearance
2
+ module Test
3
+ module Functional
4
+ module SessionsControllerTest
5
+
6
+ def self.included(controller_test)
7
+ controller_test.class_eval do
8
+
9
+ should_filter_params :password
10
+
11
+ context "on GET to /sessions/new" do
12
+ setup { get :new }
13
+
14
+ should_respond_with :success
15
+ should_render_template :new
16
+ should_not_set_the_flash
17
+ should_display_a_sign_in_form
18
+ end
19
+
20
+ context "a POST to #create with unconfirmed credentials" do
21
+ setup do
22
+ @user = Factory(:user)
23
+ ActionMailer::Base.deliveries.clear
24
+ post :create, :session => {
25
+ :email => @user.email,
26
+ :password => @user.password }
27
+ end
28
+
29
+ should_deny_access(:flash => /User has not confirmed email. Confirmation email will be resent./i)
30
+
31
+ should "send the confirmation email" do
32
+ assert_not_nil email = ActionMailer::Base.deliveries[0]
33
+ assert_match /account confirmation/i, email.subject
34
+ end
35
+ end
36
+
37
+ context "a POST to #create with good credentials" do
38
+ setup do
39
+ @user = Factory(:email_confirmed_user)
40
+ post :create, :session => {
41
+ :email => @user.email,
42
+ :password => @user.password }
43
+ end
44
+
45
+ should_set_the_flash_to /success/i
46
+ should_redirect_to_url_after_create
47
+ should_be_signed_in_as { @user }
48
+ end
49
+
50
+ context "a POST to #create with good credentials and remember me" do
51
+ setup do
52
+ @user = Factory(:email_confirmed_user)
53
+ post :create, :session => {
54
+ :email => @user.email,
55
+ :password => @user.password,
56
+ :remember_me => '1' }
57
+ end
58
+
59
+ should_set_the_flash_to /success/i
60
+ should_redirect_to_url_after_create
61
+ should_be_signed_in_as { @user }
62
+
63
+ should 'set the cookie' do
64
+ assert ! cookies['remember_token'].empty?
65
+ end
66
+
67
+ should 'set the token in users table' do
68
+ assert_not_nil @user.reload.token
69
+ assert_not_nil @user.reload.token_expires_at
70
+ end
71
+ end
72
+
73
+ context "a POST to #create with good credentials and a session return url" do
74
+ setup do
75
+ @user = Factory(:email_confirmed_user)
76
+ @return_url = '/url_in_the_session'
77
+ @request.session[:return_to] = @return_url
78
+ post :create, :session => {
79
+ :email => @user.email,
80
+ :password => @user.password }
81
+ end
82
+
83
+ should_redirect_to("the return URL") { @return_url }
84
+ end
85
+
86
+ context "a POST to #create with good credentials and a request return url" do
87
+ setup do
88
+ @user = Factory(:email_confirmed_user)
89
+ @return_url = '/url_in_the_request'
90
+ post :create, :session => {
91
+ :email => @user.email,
92
+ :password => @user.password },
93
+ :return_to => @return_url
94
+ end
95
+
96
+ should_redirect_to("the return URL") { @return_url }
97
+ end
98
+
99
+ context "a POST to #create with good credentials and a session return url and request return url" do
100
+ setup do
101
+ @user = Factory(:email_confirmed_user)
102
+ @return_url = '/url_in_the_session'
103
+ @request.session[:return_to] = @return_url
104
+ post :create, :session => {
105
+ :email => @user.email,
106
+ :password => @user.password },
107
+ :return_to => '/url_in_the_request'
108
+ end
109
+
110
+ should_redirect_to("the return URL") { @return_url }
111
+ end
112
+
113
+ context "a POST to #create with bad credentials" do
114
+ setup do
115
+ post :create, :session => {
116
+ :email => 'bad.email@example.com',
117
+ :password => "bad value" }
118
+ end
119
+
120
+ should_set_the_flash_to /bad/i
121
+ should_respond_with :unauthorized
122
+ should_render_template :new
123
+ should_not_be_signed_in
124
+ end
125
+
126
+ context "a POST to #create with bad credentials and remember me" do
127
+ setup do
128
+ post :create, :session => {
129
+ :email => 'bad.email@example.com',
130
+ :password => "bad value",
131
+ :remember_me => '1' }
132
+ end
133
+
134
+ should_set_the_flash_to /bad/i
135
+ should_respond_with :unauthorized
136
+ should_render_template :new
137
+ should_not_be_signed_in
138
+
139
+ should 'not create the cookie' do
140
+ assert_nil cookies['remember_token']
141
+ end
142
+ end
143
+
144
+ context "signing out given a signed out user" do
145
+ setup do
146
+ sign_out
147
+ delete :destroy
148
+ end
149
+ should_redirect_to_url_after_destroy
150
+ end
151
+
152
+ context "a DELETE to #destroy without a cookie" do
153
+ setup do
154
+ sign_in_as
155
+ delete :destroy
156
+ end
157
+
158
+ should_set_the_flash_to(/signed out/i)
159
+ should_redirect_to_url_after_destroy
160
+ end
161
+
162
+ context 'a DELETE to #destroy with a cookie' do
163
+ setup do
164
+ @user = Factory(:email_confirmed_user)
165
+ cookies['remember_token'] = CGI::Cookie.new('token', 'value')
166
+ sign_in_as @user
167
+ delete :destroy
168
+ end
169
+
170
+ should 'delete the cookie' do
171
+ assert cookies['remember_token'].nil? || # Rails >= 2.3
172
+ cookies['remember_token'].empty? # Rails < 2.3
173
+ end
174
+
175
+ should 'delete the remember me token in users table' do
176
+ assert_nil @user.reload.token
177
+ assert_nil @user.reload.token_expires_at
178
+ end
179
+ end
180
+
181
+ end
182
+ end
183
+
184
+ end
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,60 @@
1
+ module Clearance
2
+ module Test
3
+ module Functional
4
+ module UsersControllerTest
5
+
6
+ def self.included(controller_test)
7
+ controller_test.class_eval do
8
+
9
+ should_filter_params :password
10
+
11
+ public_context do
12
+ context "When getting new User view" do
13
+ setup { get :new }
14
+
15
+ should_respond_with :success
16
+ should_render_template :new
17
+ should_not_set_the_flash
18
+
19
+ should_display_a_sign_up_form
20
+ end
21
+
22
+ context "Given email parameter when getting new User view" do
23
+ setup do
24
+ @email = "a@example.com"
25
+ get :new, :user => { :email => @email }
26
+ end
27
+
28
+ should "set assigned user's email" do
29
+ assert_equal @email, assigns(:user).email
30
+ end
31
+ end
32
+
33
+ context "Given valid attributes when creating a new user" do
34
+ setup do
35
+ user_attributes = Factory.attributes_for(:user)
36
+ post :create, :user => user_attributes
37
+ end
38
+
39
+ should_create_user_successfully
40
+ end
41
+ end
42
+
43
+ signed_in_user_context do
44
+ context "GET to new" do
45
+ setup { get :new }
46
+ should_redirect_to("the home page") { root_url }
47
+ end
48
+
49
+ context "POST to create" do
50
+ setup { post :create, :user => {} }
51
+ should_redirect_to("the home page") { root_url }
52
+ end
53
+ end
54
+
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,65 @@
1
+ module Clearance
2
+ module Test
3
+ module Unit
4
+ module ClearanceMailerTest
5
+
6
+ def self.included(mailer_test)
7
+ mailer_test.class_eval do
8
+
9
+ context "A change password email" do
10
+ setup do
11
+ @user = Factory(:user)
12
+ @email = ClearanceMailer.create_change_password @user
13
+ end
14
+
15
+ should "set its from address to DO_NOT_REPLY" do
16
+ assert_equal DO_NOT_REPLY, @email.from[0]
17
+ end
18
+
19
+ should "contain a link to edit the user's password" do
20
+ host = ActionMailer::Base.default_url_options[:host]
21
+ regexp = %r{http://#{host}/users/#{@user.id}/password/edit\?token=#{@user.token}}
22
+ assert_match regexp, @email.body
23
+ end
24
+
25
+ should "be sent to the user" do
26
+ assert_equal [@user.email], @email.to
27
+ end
28
+
29
+ should "set its subject" do
30
+ assert_match /Change your password/, @email.subject
31
+ end
32
+ end
33
+
34
+ context "A confirmation email" do
35
+ setup do
36
+ @user = Factory(:user)
37
+ @email = ClearanceMailer.create_confirmation @user
38
+ end
39
+
40
+ should "set its recipient to the given user" do
41
+ assert_equal @user.email, @email.to[0]
42
+ end
43
+
44
+ should "set its subject" do
45
+ assert_match /Account confirmation/, @email.subject
46
+ end
47
+
48
+ should "set its from address to DO_NOT_REPLY" do
49
+ assert_equal DO_NOT_REPLY, @email.from[0]
50
+ end
51
+
52
+ should "contain a link to confirm the user's account" do
53
+ host = ActionMailer::Base.default_url_options[:host]
54
+ regexp = %r{http://#{host}/users/#{@user.id}/confirmation/new\?token=#{@user.token}}
55
+ assert_match regexp, @email.body
56
+ end
57
+ end
58
+
59
+ end
60
+ end
61
+
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,243 @@
1
+ module Clearance
2
+ module Test
3
+ module Unit
4
+ module UserTest
5
+
6
+ def self.included(unit_test)
7
+ unit_test.class_eval do
8
+
9
+ should_not_allow_mass_assignment_of :email_confirmed,
10
+ :salt, :encrypted_password,
11
+ :token, :token_expires_at
12
+
13
+ # signing up
14
+
15
+ context "When signing up" do
16
+ should_validate_presence_of :email, :password
17
+ should_allow_values_for :email, "foo@example.com"
18
+ should_not_allow_values_for :email, "foo"
19
+ should_not_allow_values_for :email, "example.com"
20
+
21
+ should "require password confirmation on create" do
22
+ user = Factory.build(:user, :password => 'blah',
23
+ :password_confirmation => 'boogidy')
24
+ assert ! user.save
25
+ assert user.errors.on(:password)
26
+ end
27
+
28
+ should "require non nil password confirmation on create" do
29
+ user = Factory.build(:user, :password => 'blah',
30
+ :password_confirmation => nil)
31
+ assert ! user.save
32
+ assert user.errors.on(:password_confirmation)
33
+ end
34
+
35
+ should "initialize salt" do
36
+ assert_not_nil Factory(:user).salt
37
+ end
38
+
39
+ should "initialize token without expiry date" do
40
+ assert_not_nil Factory(:user).token
41
+ assert_nil Factory(:user).token_expires_at
42
+ end
43
+
44
+ context "encrypt password" do
45
+ setup do
46
+ @salt = "salt"
47
+ @user = Factory.build(:user, :salt => @salt)
48
+ def @user.initialize_salt; end
49
+ @user.save!
50
+ @password = @user.password
51
+
52
+ @user.encrypt(@password)
53
+ @expected = Digest::SHA1.hexdigest("--#{@salt}--#{@password}--")
54
+ end
55
+
56
+ should "create an encrypted password using SHA1 encryption" do
57
+ assert_equal @expected, @user.encrypted_password
58
+ end
59
+ end
60
+
61
+ should "store email in exact case" do
62
+ user = Factory(:user, :email => "John.Doe@example.com")
63
+ assert_equal "John.Doe@example.com", user.email
64
+ end
65
+ end
66
+
67
+ context "When multiple users have signed up" do
68
+ setup { @user = Factory(:user) }
69
+ should_validate_uniqueness_of :email
70
+ end
71
+
72
+ # confirming email
73
+
74
+ context "A user without email confirmation" do
75
+ setup do
76
+ @user = Factory(:user)
77
+ assert ! @user.email_confirmed?
78
+ end
79
+
80
+ context "after #confirm_email!" do
81
+ setup do
82
+ assert @user.confirm_email!
83
+ @user.reload
84
+ end
85
+
86
+ should "have confirmed their email" do
87
+ assert @user.email_confirmed?
88
+ end
89
+
90
+ should "reset token" do
91
+ assert_nil @user.token
92
+ end
93
+ end
94
+ end
95
+
96
+ # authenticating
97
+
98
+ context "A user" do
99
+ setup do
100
+ @user = Factory(:user)
101
+ @password = @user.password
102
+ end
103
+
104
+ should "authenticate with good credentials" do
105
+ assert User.authenticate(@user.email, @password)
106
+ assert @user.authenticated?(@password)
107
+ end
108
+
109
+ should "not authenticate with bad credentials" do
110
+ assert ! User.authenticate(@user.email, 'bad_password')
111
+ assert ! @user.authenticated?('bad_password')
112
+ end
113
+ end
114
+
115
+ # remember me
116
+
117
+ context "When authenticating with remember_me!" do
118
+ setup do
119
+ @user = Factory(:email_confirmed_user)
120
+ @token = @user.token
121
+ assert_nil @user.token_expires_at
122
+ @user.remember_me!
123
+ end
124
+
125
+ should "set the remember token and expiration date" do
126
+ assert_not_equal @token, @user.token
127
+ assert_not_nil @user.token_expires_at
128
+ end
129
+
130
+ should "remember user when token expires in the future" do
131
+ @user.update_attribute :token_expires_at,
132
+ 2.weeks.from_now.utc
133
+ assert @user.remember?
134
+ end
135
+
136
+ should "not remember user when token has already expired" do
137
+ @user.update_attribute :token_expires_at,
138
+ 2.weeks.ago.utc
139
+ assert ! @user.remember?
140
+ end
141
+
142
+ should "not remember user when token expiry date is not set" do
143
+ @user.update_attribute :token_expires_at, nil
144
+ assert ! @user.remember?
145
+ end
146
+
147
+ # logging out
148
+
149
+ context "forget_me!" do
150
+ setup { @user.forget_me! }
151
+
152
+ should "unset the remember token and expiration date" do
153
+ assert_nil @user.token
154
+ assert_nil @user.token_expires_at
155
+ end
156
+
157
+ should "not remember user" do
158
+ assert ! @user.remember?
159
+ end
160
+ end
161
+ end
162
+
163
+ # updating password
164
+
165
+ context "An email confirmed user" do
166
+ setup do
167
+ @user = Factory(:email_confirmed_user)
168
+ @old_encrypted_password = @user.encrypted_password
169
+ end
170
+
171
+ context "who updates password with confirmation" do
172
+ setup do
173
+ @user.update_password("new_password", "new_password")
174
+ end
175
+
176
+ should "change encrypted password" do
177
+ assert_not_equal @user.encrypted_password,
178
+ @old_encrypted_password
179
+ end
180
+ end
181
+ end
182
+
183
+ # recovering forgotten password
184
+
185
+ context "An email confirmed user" do
186
+ setup do
187
+ @user = Factory(:email_confirmed_user)
188
+ @old_encrypted_password = @user.encrypted_password
189
+ @user.confirm_email!
190
+ end
191
+
192
+ context "who requests password reminder" do
193
+ setup do
194
+ assert_nil @user.token
195
+ @user.forgot_password!
196
+ end
197
+
198
+ should "generate token" do
199
+ assert_not_nil @user.token
200
+ end
201
+
202
+ context "and then updates password" do
203
+ context 'with confirmation' do
204
+ setup do
205
+ @user.update_password("new_password", "new_password")
206
+ end
207
+
208
+ should "change encrypted password" do
209
+ assert_not_equal @user.encrypted_password,
210
+ @old_encrypted_password
211
+ end
212
+
213
+ should "clear token" do
214
+ assert_nil @user.token
215
+ end
216
+ end
217
+
218
+ context 'without confirmation' do
219
+ setup do
220
+ @user.update_password("new_password", "")
221
+ end
222
+
223
+ should "not change encrypted password" do
224
+ assert_equal @user.encrypted_password,
225
+ @old_encrypted_password
226
+ end
227
+
228
+ should "not clear token" do
229
+ assert_not_nil @user.token
230
+ end
231
+ end
232
+ end
233
+ end
234
+
235
+ end
236
+
237
+ end
238
+ end
239
+
240
+ end
241
+ end
242
+ end
243
+ end