clearance 1.7.0 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of clearance might be problematic. Click here for more details.

Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -3
  3. data/Gemfile.lock +4 -28
  4. data/NEWS.md +12 -0
  5. data/README.md +8 -1
  6. data/Rakefile +11 -8
  7. data/app/controllers/clearance/passwords_controller.rb +1 -0
  8. data/app/controllers/clearance/sessions_controller.rb +14 -2
  9. data/app/controllers/clearance/users_controller.rb +15 -4
  10. data/bin/appraisal +16 -0
  11. data/bin/rake +16 -0
  12. data/bin/rspec +16 -0
  13. data/clearance.gemspec +1 -1
  14. data/gemfiles/rails3.2.gemfile +1 -3
  15. data/gemfiles/rails4.0.gemfile +1 -3
  16. data/gemfiles/rails4.1.gemfile +1 -3
  17. data/gemfiles/rails4.2.gemfile +1 -3
  18. data/lib/clearance/configuration.rb +2 -0
  19. data/lib/clearance/session.rb +12 -6
  20. data/lib/clearance/version.rb +1 -1
  21. data/spec/acceptance/clearance_installation_spec.rb +75 -0
  22. data/spec/{support/app_templates → app_templates}/app/controllers/application_controller.rb +0 -0
  23. data/spec/{support/app_templates → app_templates}/app/models/user.rb +0 -0
  24. data/spec/{support/app_templates → app_templates}/config/routes.rb +0 -0
  25. data/spec/app_templates/testapp/Gemfile +7 -0
  26. data/spec/app_templates/testapp/app/controllers/home_controller.rb +5 -0
  27. data/spec/app_templates/testapp/config/initializers/action_mailer.rb +3 -0
  28. data/spec/app_templates/testapp/config/routes.rb +3 -0
  29. data/spec/clearance/session_spec.rb +13 -0
  30. data/spec/controllers/passwords_controller_spec.rb +100 -131
  31. data/spec/controllers/sessions_controller_spec.rb +66 -52
  32. data/spec/controllers/users_controller_spec.rb +47 -60
  33. data/spec/dummy/app/models/user.rb +3 -0
  34. data/spec/dummy/app/models/user_with_optional_password.rb +7 -0
  35. data/spec/dummy/application.rb +2 -0
  36. data/spec/factories.rb +4 -0
  37. data/spec/{models → password_strategies}/bcrypt_migration_from_sha1_spec.rb +1 -0
  38. data/spec/password_strategies/bcrypt_spec.rb +81 -0
  39. data/spec/password_strategies/blowfish_spec.rb +55 -0
  40. data/spec/password_strategies/password_strategies_spec.rb +28 -0
  41. data/spec/password_strategies/sha1_spec.rb +53 -0
  42. data/spec/support/clearance.rb +0 -16
  43. data/spec/support/fake_model_with_password_strategy.rb +0 -4
  44. data/spec/support/fake_model_without_password_strategy.rb +19 -0
  45. data/spec/support/generator_spec_helpers.rb +1 -1
  46. data/spec/support/request_with_remember_token.rb +1 -1
  47. data/spec/user_spec.rb +186 -0
  48. metadata +23 -67
  49. data/cucumber.yml +0 -1
  50. data/features/integration_with_rspec.feature +0 -23
  51. data/features/integration_with_test_unit.feature +0 -16
  52. data/features/step_definitions/configuration_steps.rb +0 -153
  53. data/features/step_definitions/gem_file_steps.rb +0 -15
  54. data/features/support/aruba.rb +0 -3
  55. data/features/support/env.rb +0 -27
  56. data/spec/models/bcrypt_spec.rb +0 -66
  57. data/spec/models/blowfish_spec.rb +0 -42
  58. data/spec/models/password_strategies_spec.rb +0 -41
  59. data/spec/models/sha1_spec.rb +0 -43
  60. data/spec/models/user_spec.rb +0 -196
@@ -1,3 +1,3 @@
1
1
  module Clearance
2
- VERSION = "1.7.0"
2
+ VERSION = "1.8.0"
3
3
  end
@@ -0,0 +1,75 @@
1
+ require "spec_helper"
2
+
3
+ describe "Clearance Installation" do
4
+ around do |example|
5
+ Dir.chdir("tmp") do
6
+ FileUtils.rm_rf("testapp")
7
+ example.run
8
+ end
9
+ end
10
+
11
+ it "can successfully run specs" do
12
+ app_name = "testapp"
13
+ generate_test_app(app_name)
14
+
15
+ Dir.chdir(app_name) do
16
+ configure_test_app
17
+ install_dependencies
18
+ configure_rspec
19
+ install_clearance
20
+ run_specs
21
+ end
22
+ end
23
+
24
+ def generate_test_app(app_name)
25
+ successfully "bundle exec rails new #{app_name} \
26
+ --skip-gemfile \
27
+ --skip-bundle \
28
+ --skip-git \
29
+ --skip-javascript \
30
+ --skip-sprockets \
31
+ --skip-keeps"
32
+
33
+ FileUtils.rm_f("public/index.html")
34
+ FileUtils.rm_f("app/views/layouts/application.html.erb")
35
+ end
36
+
37
+ def testapp_templates
38
+ File.expand_path("../../app_templates/testapp/", __FILE__)
39
+ end
40
+
41
+ def configure_test_app
42
+ FileUtils.rm_f("public/index.html")
43
+ FileUtils.rm_f("app/views/layouts/application.html.erb")
44
+ FileUtils.cp_r(testapp_templates, "..")
45
+ end
46
+
47
+ def install_dependencies
48
+ successfully "bundle install --local"
49
+ end
50
+
51
+ def configure_rspec
52
+ successfully "bundle exec rails generate rspec:install"
53
+ end
54
+
55
+ def install_clearance
56
+ successfully "bundle exec rails generate clearance:install"
57
+ successfully "bundle exec rails generate clearance:specs"
58
+ successfully "bundle exec rake db:migrate db:test:prepare"
59
+ end
60
+
61
+ def run_specs
62
+ successfully "bundle exec rspec", false
63
+ end
64
+
65
+ def successfully(command, silent = true)
66
+ if silent
67
+ silencer = "1>/dev/null"
68
+ else
69
+ silencer = ""
70
+ end
71
+
72
+ return_value = system("#{command} #{silencer}")
73
+ expect(return_value).to eq true
74
+ end
75
+ end
@@ -0,0 +1,7 @@
1
+ gem "rails"
2
+ gem "sqlite3"
3
+ gem "rspec-rails"
4
+ gem "capybara"
5
+ gem "factory_girl_rails"
6
+ gem "database_cleaner"
7
+ gem "clearance", path: "../.."
@@ -0,0 +1,5 @@
1
+ class HomeController < ApplicationController
2
+ def show
3
+ render text: "", layout: "application"
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ Rails.application.config.action_mailer.default_url_options = {
2
+ host: "localhost"
3
+ }
@@ -0,0 +1,3 @@
1
+ Rails.application.routes.draw do
2
+ root to: "home#show"
3
+ end
@@ -30,6 +30,19 @@ describe Clearance::Session do
30
30
  expect(session.current_user).to be_nil
31
31
  end
32
32
 
33
+ context "with a custom cookie name" do
34
+ it "sets a custom cookie name in the header" do
35
+ Clearance.configuration.cookie_domain = "custom_token"
36
+
37
+ session.sign_in user
38
+ session.add_cookie_to_headers(headers)
39
+
40
+ expect(headers["Set-Cookie"]).to match(/custom_token/)
41
+ end
42
+
43
+ after { restore_default_config }
44
+ end
45
+
33
46
  describe '#sign_in' do
34
47
  it 'sets current_user' do
35
48
  user = build(:user)
@@ -1,188 +1,157 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  describe Clearance::PasswordsController do
4
4
  it { is_expected.to be_a Clearance::BaseController }
5
5
 
6
- describe 'a signed up user' do
7
- before do
8
- @user = create(:user)
9
- end
6
+ describe "#new" do
7
+ it "renders the password reset form" do
8
+ user = create(:user)
10
9
 
11
- describe 'on GET to #new' do
12
- before { get :new, user_id: @user.to_param }
10
+ get :new, user_id: user
13
11
 
14
- it { is_expected.to respond_with(:success) }
15
- it { is_expected.to render_template(:new) }
12
+ expect(response).to be_success
13
+ expect(response).to render_template(:new)
16
14
  end
15
+ end
17
16
 
18
- describe 'on POST to #create' do
19
- describe 'with correct email address' do
20
- before do
21
- ActionMailer::Base.deliveries.clear
22
- post :create, password: { email: @user.email }
23
- end
24
-
25
- it 'should generate a token for the change your password email' do
26
- expect(@user.reload.confirmation_token).not_to be_nil
27
- end
17
+ describe "#create" do
18
+ context "email corresponds to an existing user" do
19
+ it "generates a password change token" do
20
+ user = create(:user)
28
21
 
29
- it 'sends an email with relevant subject' do
30
- email = ActionMailer::Base.deliveries.last
31
- expect(email.subject).to match(/change your password/i)
32
- end
22
+ post :create, password: { email: user.email.upcase }
33
23
 
34
- it { is_expected.to respond_with(:success) }
24
+ expect(user.reload.confirmation_token).not_to be_nil
35
25
  end
36
26
 
37
- describe 'with correct email address capitalized differently' do
38
- before do
39
- ActionMailer::Base.deliveries.clear
40
- post :create, password: { email: @user.email.upcase }
41
- end
42
-
43
- it 'should generate a token for the change your password email' do
44
- expect(@user.reload.confirmation_token).not_to be_nil
45
- end
27
+ it "sends the password reset email" do
28
+ ActionMailer::Base.deliveries.clear
29
+ user = create(:user)
46
30
 
47
- it 'sends an email with relevant subject' do
48
- email = ActionMailer::Base.deliveries.last
49
- expect(email.subject).to match(/change your password/i)
50
- end
31
+ post :create, password: { email: user.email }
51
32
 
52
- it { is_expected.to respond_with(:success) }
33
+ email = ActionMailer::Base.deliveries.last
34
+ expect(email.subject).to match(/change your password/i)
53
35
  end
36
+ end
54
37
 
55
- describe 'with incorrect email address' do
56
- before do
57
- email = 'user1@example.com'
58
- user = Clearance.configuration.user_model.exists?(email: email)
59
- expect(user).not_to be_present
38
+ context "email does not belong to an existing user" do
39
+ it "does not deliver an email" do
40
+ ActionMailer::Base.deliveries.clear
41
+ email = "this_user_does_not_exist@non_existent_domain.com"
60
42
 
61
- ActionMailer::Base.deliveries.clear
62
- expect(@user.reload.confirmation_token).to eq @user.confirmation_token
43
+ post :create, password: { email: email }
63
44
 
64
- post :create, password: { email: email }
65
- end
45
+ expect(ActionMailer::Base.deliveries).to be_empty
46
+ end
66
47
 
67
- it 'should not generate a token for the change your password email' do
68
- expect(@user.reload.confirmation_token).to eq @user.confirmation_token
69
- end
48
+ it "still responds with success so as not to leak registered users" do
49
+ email = "this_user_does_not_exist@non_existent_domain.com"
70
50
 
71
- it 'should not send a password reminder email' do
72
- expect(ActionMailer::Base.deliveries).to be_empty
73
- end
51
+ post :create, password: { email: email }
74
52
 
75
- it { is_expected.to render_template(:create) }
53
+ expect(response).to be_success
54
+ expect(response).to render_template "passwords/create"
76
55
  end
77
56
  end
78
57
  end
79
58
 
80
- describe 'a signed up user and forgotten password' do
81
- before do
82
- @user = create(:user)
83
- @user.forgot_password!
84
- end
59
+ describe "#edit" do
60
+ context "valid id and token are supplied" do
61
+ it "renders the password form for the user" do
62
+ user = create(:user, :with_forgotten_password)
85
63
 
86
- describe 'on GET to #edit with correct id and token' do
87
- before do
88
- get :edit,
89
- user_id: @user.to_param,
90
- token: @user.confirmation_token
91
- end
64
+ get :edit, user_id: user, token: user.confirmation_token
92
65
 
93
- it 'should find the user' do
94
- expect(assigns(:user)).to eq @user
66
+ expect(response).to be_success
67
+ expect(response).to render_template(:edit)
68
+ expect(assigns(:user)).to eq user
95
69
  end
96
-
97
- it { is_expected.to respond_with(:success) }
98
- it { is_expected.to render_template(:edit) }
99
70
  end
100
71
 
101
- describe 'on GET to #edit with correct id but blank token' do
102
- before do
103
- get :edit, user_id: @user.to_param, token: ''
104
- end
72
+ context "blank token is supplied" do
73
+ it "renders the new password reset form with a flash notice" do
74
+ get :edit, user_id: 1, token: ""
105
75
 
106
- it { is_expected.to set_the_flash.to(/double check the URL/i).now }
107
- it { is_expected.to render_template(:new) }
76
+ expect(response).to render_template(:new)
77
+ expect(flash.now[:notice]).to match(/double check the URL/i)
78
+ end
108
79
  end
109
80
 
110
- describe 'on GET to #edit with correct id but no token' do
111
- before do
112
- get :edit, user_id: @user.to_param
113
- end
81
+ context "invalid token is supplied" do
82
+ it "renders the new password reset form with a flash notice" do
83
+ user = create(:user, :with_forgotten_password)
114
84
 
115
- it { is_expected.to set_the_flash.to(/double check the URL/i).now }
116
- it { is_expected.to render_template(:new) }
85
+ get :edit, user_id: 1, token: user.confirmation_token + "a"
86
+
87
+ expect(response).to render_template(:new)
88
+ expect(flash.now[:notice]).to match(/double check the URL/i)
89
+ end
117
90
  end
91
+ end
118
92
 
119
- describe 'on PUT to #update with password' do
120
- before do
121
- @new_password = 'new_password'
122
- @old_encrypted_password = @user.encrypted_password
93
+ describe "#update" do
94
+ context "valid id, token, and new password provided" do
95
+ it "updates the user's password" do
96
+ user = create(:user, :with_forgotten_password)
97
+ old_encrypted_password = user.encrypted_password
123
98
 
124
- put :update, user_id: @user, token: @user.confirmation_token,
125
- password_reset: { password: @new_password }
126
- @user.reload
127
- end
99
+ put :update, update_parameters(user, new_password: "my_new_password")
128
100
 
129
- it 'should update password' do
130
- expect(@user.encrypted_password.to_s).not_to eq @old_encrypted_password
101
+ expect(user.reload.encrypted_password).not_to eq old_encrypted_password
131
102
  end
132
103
 
133
- it 'should clear confirmation token' do
134
- expect(@user.confirmation_token).to be_nil
135
- end
104
+ it "sets the remember token and clears the confirmation token" do
105
+ user = create(:user, :with_forgotten_password)
136
106
 
137
- it 'should set remember token' do
138
- expect(@user.remember_token).not_to be_nil
107
+ put :update, update_parameters(user, new_password: "my_new_password")
108
+
109
+ user.reload
110
+ expect(user.remember_token).not_to be_nil
111
+ expect(user.confirmation_token).to be_nil
139
112
  end
140
113
 
141
- it { is_expected.to redirect_to_url_after_update }
142
- end
114
+ it "signs the user in and redirects" do
115
+ user = create(:user, :with_forgotten_password)
143
116
 
144
- describe 'on PUT to #update with blank password' do
145
- before do
146
- put :update, user_id: @user.to_param, token: @user.confirmation_token,
147
- password_reset: { password: '' }
148
- @user.reload
149
- end
117
+ put :update, update_parameters(user, new_password: "my_new_password")
150
118
 
151
- it 'should not update password to be blank' do
152
- expect(@user.encrypted_password).not_to be_blank
119
+ expect(response).to redirect_to(Clearance.configuration.redirect_url)
120
+ expect(cookies[:remember_token]).to be_present
153
121
  end
122
+ end
154
123
 
155
- it 'should not clear token' do
156
- expect(@user.confirmation_token).not_to be_nil
157
- end
124
+ context "no password provided" do
125
+ it "does not update the password" do
126
+ user = create(:user, :with_forgotten_password)
127
+ old_encrypted_password = user.encrypted_password
158
128
 
159
- it 'should not be signed in' do
160
- expect(cookies[:remember_token]).to be_nil
129
+ put :update, update_parameters(user, new_password: "")
130
+
131
+ user.reload
132
+ expect(user.encrypted_password).to eq old_encrypted_password
133
+ expect(user.confirmation_token).to be_present
161
134
  end
162
135
 
163
- it { is_expected.to set_the_flash.to(/password can't be blank/i).now }
164
- it { is_expected.to respond_with(:success) }
165
- it { is_expected.to render_template(:edit) }
166
- end
136
+ it "re-renders the password edit form" do
137
+ user = create(:user, :with_forgotten_password)
167
138
 
168
- describe 'on PUT to #update with an empty token after the user sets a password' do
169
- before do
170
- put :update, user_id: @user.to_param, token: @user.confirmation_token,
171
- password_reset: { password: 'good password' }
172
- put :update, user_id: @user.to_param, token: [nil],
173
- password_reset: { password: 'new password' }
174
- end
139
+ put :update, update_parameters(user, new_password: "")
175
140
 
176
- it { is_expected.to set_the_flash.to(/double check the URL/i).now }
177
- it { is_expected.to render_template(:new) }
141
+ expect(flash.now[:notice]).to match(/password can't be blank/i)
142
+ expect(response).to render_template(:edit)
143
+ expect(cookies[:remember_token]).to be_nil
144
+ end
178
145
  end
179
146
  end
180
147
 
181
- describe 'given two users and user one signs in' do
182
- before do
183
- @user_one = create(:user)
184
- @user_two = create(:user)
185
- sign_in_as @user_one
186
- end
148
+ def update_parameters(user, options = {})
149
+ new_password = options.fetch(:new_password)
150
+
151
+ {
152
+ user_id: user,
153
+ token: user.confirmation_token,
154
+ password_reset: { password: new_password }
155
+ }
187
156
  end
188
157
  end
@@ -1,19 +1,31 @@
1
- require 'spec_helper'
1
+ require "spec_helper"
2
2
 
3
3
  describe Clearance::SessionsController do
4
4
  it { should be_a Clearance::BaseController }
5
5
 
6
- describe 'on GET to /sessions/new' do
7
- before { get :new }
6
+ describe "on GET to #new" do
7
+ context "when a user is not signed in" do
8
+ before { get :new }
8
9
 
9
- it { should respond_with(:success) }
10
- it { should render_template(:new) }
11
- it { should_not set_the_flash }
10
+ it { should respond_with(:success) }
11
+ it { should render_template(:new) }
12
+ it { should_not set_the_flash }
13
+ end
14
+
15
+ context "when a user is signed in" do
16
+ before do
17
+ sign_in
18
+ get :new
19
+ end
20
+
21
+ it { should redirect_to(Clearance.configuration.redirect_url) }
22
+ it { should_not set_the_flash }
23
+ end
12
24
  end
13
25
 
14
- context 'when password is optional' do
15
- describe 'POST create' do
16
- it 'renders the page with error' do
26
+ describe "on POST to #create" do
27
+ context "when password is optional" do
28
+ it "renders the page with error" do
17
29
  user = create(:user_with_optional_password)
18
30
 
19
31
  post :create, session: { email: user.email, password: user.password }
@@ -22,64 +34,66 @@ describe Clearance::SessionsController do
22
34
  expect(flash[:notice]).to match(/^Bad email or password/)
23
35
  end
24
36
  end
25
- end
26
37
 
27
- describe 'on POST to #create with good credentials' do
28
- before do
29
- @user = create(:user)
30
- @user.update_attribute :remember_token, 'old-token'
31
- post :create, session: { email: @user.email, password: @user.password }
32
- end
38
+ context "with good credentials" do
39
+ before do
40
+ @user = create(:user)
41
+ @user.update_attribute :remember_token, "old-token"
42
+ post :create, session: { email: @user.email, password: @user.password }
43
+ end
33
44
 
34
- it { should redirect_to_url_after_create }
45
+ it { should redirect_to_url_after_create }
35
46
 
36
- it 'sets the user in the clearance session' do
37
- expect(controller.current_user).to eq @user
38
- end
47
+ it "sets the user in the clearance session" do
48
+ expect(controller.current_user).to eq @user
49
+ end
39
50
 
40
- it 'should not change the remember token' do
41
- expect(@user.reload.remember_token).to eq 'old-token'
51
+ it "should not change the remember token" do
52
+ expect(@user.reload.remember_token).to eq "old-token"
53
+ end
42
54
  end
43
- end
44
55
 
45
- describe 'on POST to #create with good credentials and a session return url' do
46
- before do
47
- @user = create(:user)
48
- @return_url = '/url_in_the_session?foo=bar'
49
- @request.session[:return_to] = @return_url
50
- post :create, session: { email: @user.email, password: @user.password }
51
- end
56
+ context "with good credentials and a session return url" do
57
+ before do
58
+ @user = create(:user)
59
+ @return_url = "/url_in_the_session?foo=bar"
60
+ @request.session[:return_to] = @return_url
61
+ post :create, session: { email: @user.email, password: @user.password }
62
+ end
52
63
 
53
- it 'redirects to the return URL' do
54
- should redirect_to(@return_url)
64
+ it "redirects to the return URL" do
65
+ should redirect_to(@return_url)
66
+ end
55
67
  end
56
68
  end
57
69
 
58
- describe 'on DELETE to #destroy given a signed out user' do
59
- before do
60
- sign_out
61
- delete :destroy
62
- end
63
-
64
- it { should redirect_to_url_after_destroy }
65
- end
70
+ describe "on DELETE to #destroy" do
71
+ context "given a signed out user" do
72
+ before do
73
+ sign_out
74
+ delete :destroy
75
+ end
66
76
 
67
- describe 'on DELETE to #destroy with a cookie' do
68
- before do
69
- @user = create(:user)
70
- @user.update_attribute :remember_token, 'old-token'
71
- @request.cookies['remember_token'] = 'old-token'
72
- delete :destroy
77
+ it { should redirect_to_url_after_destroy }
73
78
  end
74
79
 
75
- it { should redirect_to_url_after_destroy }
80
+ context "with a cookie" do
81
+ before do
82
+ @user = create(:user)
83
+ @user.update_attribute :remember_token, "old-token"
84
+ @request.cookies["remember_token"] = "old-token"
85
+ delete :destroy
86
+ end
76
87
 
77
- it 'should reset the remember token' do
78
- expect(@user.reload.remember_token).not_to eq 'old-token'
79
- end
88
+ it { should redirect_to_url_after_destroy }
80
89
 
81
- it 'should unset the current user' do
82
- expect(@controller.current_user).to be_nil
90
+ it "should reset the remember token" do
91
+ expect(@user.reload.remember_token).not_to eq "old-token"
92
+ end
93
+
94
+ it "should unset the current user" do
95
+ expect(@controller.current_user).to be_nil
96
+ end
83
97
  end
84
98
  end
85
99
  end