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,15 +0,0 @@
1
- When /^I add the "([^"]*)" gem$/ do |gem_name|
2
- append_to_file('Gemfile', %{\ngem "#{gem_name}"\n})
3
- end
4
-
5
- When /^I add the "([^"]*)" gem from this project$/ do |gem_name|
6
- append_to_file('Gemfile', %{\ngem "#{gem_name}", path: "../../.."\n})
7
- end
8
-
9
- When /^I remove the "([^"]*)" gem from this project$/ do |gem_name|
10
- in_current_dir do
11
- content = File.read('Gemfile')
12
- content.sub!(/^.*gem '#{gem_name}'.*\n/, "")
13
- File.open('Gemfile', 'w') { |file| file.write(content) }
14
- end
15
- end
@@ -1,3 +0,0 @@
1
- Before do
2
- @aruba_timeout_seconds = 60
3
- end
@@ -1,27 +0,0 @@
1
- ENV["RAILS_ENV"] ||= "test"
2
-
3
- require "bundler"
4
- require "rails/all"
5
-
6
- require "clearance"
7
- require "aruba/cucumber"
8
- require_relative "../../spec/dummy/application"
9
- require "cucumber/rails/action_controller"
10
- require "cucumber/rails/application"
11
- require "cucumber/rails/capybara"
12
- require "cucumber/rails/database"
13
- require "cucumber/rails/hooks"
14
- require "cucumber/rails/world"
15
-
16
- ActionController::Base.allow_rescue = false
17
- Capybara.default_selector = :css
18
- Capybara.save_and_open_page_path = "tmp"
19
- Dummy::Application.initialize!
20
-
21
- DatabaseCleaner.strategy = :transaction
22
-
23
- Around do |scenario, block|
24
- Bundler.with_clean_env do
25
- block.call
26
- end
27
- end
@@ -1,66 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Clearance::PasswordStrategies::BCrypt do
4
- subject do
5
- fake_model_with_password_strategy(Clearance::PasswordStrategies::BCrypt)
6
- end
7
-
8
- describe '#password=' do
9
- let(:password) { 'password' }
10
- let(:encrypted_password) { double("encrypted password") }
11
-
12
- before do
13
- allow(BCrypt::Password).to receive(:create).and_return(encrypted_password)
14
- end
15
-
16
- it 'encrypts the password into encrypted_password' do
17
- subject.password = password
18
-
19
- expect(subject.encrypted_password).to eq encrypted_password
20
- end
21
-
22
- it 'encrypts with BCrypt using default cost in non test environments' do
23
- allow(Rails).to receive(:env).
24
- and_return(ActiveSupport::StringInquirer.new("production"))
25
-
26
- subject.password = password
27
-
28
- expect(BCrypt::Password).to have_received(:create).with(
29
- password,
30
- cost: ::BCrypt::Engine::DEFAULT_COST
31
- )
32
- end
33
-
34
- it 'encrypts with BCrypt using minimum cost in test environment' do
35
- subject.password = password
36
-
37
- expect(BCrypt::Password).to have_received(:create).with(
38
- password,
39
- cost: ::BCrypt::Engine::MIN_COST
40
- )
41
- end
42
- end
43
-
44
- describe '#authenticated?' do
45
-
46
- before do
47
- subject.password = password
48
- end
49
-
50
- context 'given a password' do
51
- let(:password) { 'password' }
52
-
53
- it 'is authenticated with BCrypt' do
54
- expect(subject).to be_authenticated(password)
55
- end
56
- end
57
-
58
- context 'given no password' do
59
- let(:password) { nil }
60
-
61
- it 'is not authenticated' do
62
- expect(subject).not_to be_authenticated(password)
63
- end
64
- end
65
- end
66
- end
@@ -1,42 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Clearance::PasswordStrategies::Blowfish do
4
- subject do
5
- fake_model_with_password_strategy(Clearance::PasswordStrategies::Blowfish)
6
- end
7
-
8
- describe '#password=' do
9
- context 'when the password is set' do
10
- let(:salt) { 'salt' }
11
- let(:password) { 'password' }
12
-
13
- before do
14
- subject.salt = salt
15
- subject.password = password
16
- end
17
-
18
- it 'does not initialize the salt' do
19
- expect(subject.salt).to eq salt
20
- end
21
-
22
- it 'encrypts the password using Blowfish and the existing salt' do
23
- cipher = OpenSSL::Cipher::Cipher.new('bf-cbc').encrypt
24
- cipher.key = Digest::SHA256.digest(salt)
25
- expected = cipher.update("--#{salt}--#{password}--") << cipher.final
26
- encrypted_password = Base64.decode64(subject.encrypted_password)
27
- expect(encrypted_password).to eq expected
28
- end
29
- end
30
-
31
- context 'when the salt is not set' do
32
- before do
33
- subject.salt = nil
34
- subject.password = 'whatever'
35
- end
36
-
37
- it 'should initialize the salt' do
38
- expect(subject.salt).not_to be_nil
39
- end
40
- end
41
- end
42
- end
@@ -1,41 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Clearance::User do
4
- subject do
5
- class UniquenessValidator < ActiveModel::Validator
6
- undef validate
7
-
8
- def validate(record)
9
- end
10
- end
11
-
12
- Class.new do
13
- include ActiveModel::Validations
14
-
15
- validates_with UniquenessValidator
16
-
17
- def self.before_validation(*args); end
18
- def self.before_create(*args); end
19
-
20
- include Clearance::User
21
- end.new
22
- end
23
-
24
- describe 'when Clearance.configuration.password_strategy is set' do
25
- let(:mock_password_strategy) { Module.new }
26
-
27
- before { Clearance.configuration.password_strategy = mock_password_strategy }
28
-
29
- it 'includes the value it is set to' do
30
- expect(subject).to be_kind_of(mock_password_strategy)
31
- end
32
- end
33
-
34
- describe 'when Clearance.configuration.password_strategy is not set' do
35
- before { Clearance.configuration.password_strategy = nil }
36
-
37
- it 'includes Clearance::PasswordStrategies::BCrypt' do
38
- expect(subject).to be_kind_of(Clearance::PasswordStrategies::BCrypt)
39
- end
40
- end
41
- end
@@ -1,43 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Clearance::PasswordStrategies::SHA1 do
4
- subject do
5
- fake_model_with_password_strategy(Clearance::PasswordStrategies::SHA1)
6
- end
7
-
8
- describe '#password=' do
9
- context 'when the password is set' do
10
- let(:salt) { 'salt' }
11
- let(:password) { 'password' }
12
-
13
- before do
14
- subject.salt = salt
15
- subject.password = password
16
- end
17
-
18
- it 'does not initialize the salt' do
19
- expect(subject.salt).to eq salt
20
- end
21
-
22
- it 'encrypts the password using SHA1 and the existing salt' do
23
- expected = Digest::SHA1.hexdigest("--#{salt}--#{password}--")
24
- expect(subject.encrypted_password).to eq expected
25
- end
26
- end
27
-
28
- context "when the password is not set" do
29
- before do
30
- subject.salt = nil
31
- subject.password = ""
32
- end
33
-
34
- it "initializes the salt" do
35
- expect(subject.salt).not_to be_nil
36
- end
37
-
38
- it "doesn't encrpt the password" do
39
- expect(subject.encrypted_password).to be_nil
40
- end
41
- end
42
- end
43
- end
@@ -1,196 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe User do
4
- it { should have_db_index(:email) }
5
- it { should have_db_index(:remember_token) }
6
-
7
- describe 'when signing up' do
8
- it { is_expected.to validate_presence_of(:email) }
9
- it { is_expected.to validate_presence_of(:password) }
10
- it { is_expected.to allow_value('foo@example.co.uk').for(:email) }
11
- it { is_expected.to allow_value('foo@example.com').for(:email) }
12
- it { is_expected.to allow_value('foo+bar@example.com').for(:email) }
13
- it { is_expected.not_to allow_value('foo@').for(:email) }
14
- it { is_expected.not_to allow_value('foo@example..com').for(:email) }
15
- it { is_expected.not_to allow_value('foo@.example.com').for(:email) }
16
- it { is_expected.not_to allow_value('foo').for(:email) }
17
- it { is_expected.not_to allow_value('example.com').for(:email) }
18
- it { is_expected.not_to allow_value('foo;@example.com').for(:email) }
19
-
20
- it 'stores email in down case and removes whitespace' do
21
- user = create(:user, email: 'Jo hn.Do e @exa mp le.c om')
22
- expect(user.email).to eq 'john.doe@example.com'
23
- end
24
- end
25
-
26
- describe 'when multiple users have signed up' do
27
- before { create(:user) }
28
- it { is_expected.to validate_uniqueness_of(:email) }
29
- end
30
-
31
- describe 'a user' do
32
- before do
33
- @user = create(:user)
34
- @password = @user.password
35
- end
36
-
37
- it 'is authenticated with correct email and password' do
38
- expect(User.authenticate(@user.email, @password)).to eq(@user)
39
- expect(@user).to be_authenticated(@password)
40
- end
41
-
42
- it 'is authenticated with correct uppercased email and correct password' do
43
- expect(User.authenticate(@user.email.upcase, @password)).to eq(@user)
44
- expect(@user).to be_authenticated(@password)
45
- end
46
-
47
- it 'is not authenticated with incorrect credentials' do
48
- expect(User.authenticate(@user.email, 'bad_password')).to be_nil
49
- expect(@user).not_to be_authenticated('bad password')
50
- end
51
-
52
- it 'is retrieved via a case-insensitive search' do
53
- expect(User.find_by_normalized_email(@user.email.upcase)).to eq(@user)
54
- end
55
- end
56
-
57
- describe 'when resetting authentication with reset_remember_token!' do
58
- before do
59
- @user = create(:user)
60
- @user.remember_token = 'old-token'
61
- @user.reset_remember_token!
62
- end
63
-
64
- it 'changes the remember token' do
65
- expect(@user.remember_token).not_to eq 'old-token'
66
- end
67
- end
68
-
69
- describe 'an email confirmed user' do
70
- before do
71
- @user = create(:user)
72
- @old_encrypted_password = @user.encrypted_password
73
- end
74
-
75
- describe 'who updates password' do
76
- before do
77
- @user.update_password('new_password')
78
- end
79
-
80
- it 'changes encrypted password' do
81
- expect(@user.encrypted_password).not_to eq @old_encrypted_password
82
- end
83
- end
84
- end
85
-
86
- it 'does not generate same remember token for users with same password at same time' do
87
- allow(Time).to receive(:now).and_return(Time.now)
88
- password = 'secret'
89
- first_user = create(:user, password: password)
90
- second_user = create(:user, password: password)
91
- expect(second_user.remember_token).not_to eq first_user.remember_token
92
- end
93
-
94
- describe 'a user' do
95
- before do
96
- @user = create(:user)
97
- @old_encrypted_password = @user.encrypted_password
98
- end
99
-
100
- describe 'who requests password reminder' do
101
- before do
102
- expect(@user.confirmation_token).to be_nil
103
- @user.forgot_password!
104
- end
105
-
106
- it 'generates confirmation token' do
107
- expect(@user.confirmation_token).not_to be_nil
108
- end
109
-
110
- describe 'and then updates password' do
111
- describe 'with password' do
112
- before do
113
- @user.update_password 'new_password'
114
- end
115
-
116
- it 'changes encrypted password' do
117
- expect(@user.encrypted_password).not_to eq @old_encrypted_password
118
- end
119
-
120
- it 'clears confirmation token' do
121
- expect(@user.confirmation_token).to be_nil
122
- end
123
- end
124
-
125
- describe 'with blank password' do
126
- before do
127
- @user.update_password ''
128
- end
129
-
130
- it 'does not change encrypted password' do
131
- expect(@user.encrypted_password.to_s).to eq @old_encrypted_password
132
- end
133
-
134
- it 'does not clear confirmation token' do
135
- expect(@user.confirmation_token).to_not be_nil
136
- end
137
- end
138
- end
139
- end
140
- end
141
-
142
- describe 'a user with an optional email' do
143
- before do
144
- @user = User.new
145
-
146
- class << @user
147
- def email_optional?
148
- true
149
- end
150
- end
151
- end
152
-
153
- subject { @user }
154
-
155
- it { is_expected.to allow_value(nil).for(:email) }
156
- it { is_expected.to allow_value('').for(:email) }
157
- end
158
-
159
- describe 'user factory' do
160
- it 'should create a valid user with just an overridden password' do
161
- expect(build(:user, password: 'test')).to be_valid
162
- end
163
- end
164
-
165
- describe 'email address normalization' do
166
- let(:email) { 'Jo hn.Do e @exa mp le.c om' }
167
-
168
- it 'downcases the address and strips spaces' do
169
- expect(User.normalize_email(email)).to eq 'john.doe@example.com'
170
- end
171
- end
172
-
173
- describe 'the password setter on a User' do
174
- let(:password) { 'a-password' }
175
- before { subject.send(:password=, password) }
176
-
177
- it 'sets password to the plain-text password' do
178
- expect(subject.password).to eq password
179
- end
180
-
181
- it 'also sets encrypted_password' do
182
- expect(subject.encrypted_password).to_not be_nil
183
- end
184
- end
185
- end
186
-
187
- describe UserWithOptionalPassword do
188
- it { is_expected.to allow_value(nil).for(:password) }
189
- it { is_expected.to allow_value('').for(:password) }
190
-
191
- it 'cannot authenticate with blank password' do
192
- user = create(:user_with_optional_password)
193
-
194
- expect(UserWithOptionalPassword.authenticate(user.email, '')).to be_nil
195
- end
196
- end