authenticate 0.2.3 → 0.3.0

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -4
  3. data/CHANGELOG.md +12 -0
  4. data/Gemfile +1 -0
  5. data/Gemfile.lock +21 -6
  6. data/app/controllers/authenticate/passwords_controller.rb +1 -1
  7. data/authenticate.gemspec +7 -3
  8. data/config/locales/authenticate.en.yml +1 -1
  9. data/gemfiles/rails42.gemfile +6 -1
  10. data/lib/authenticate/callbacks/brute_force.rb +3 -4
  11. data/lib/authenticate/configuration.rb +2 -2
  12. data/lib/authenticate/controller.rb +1 -2
  13. data/lib/authenticate/model/brute_force.rb +2 -2
  14. data/lib/authenticate/model/db_password.rb +2 -3
  15. data/lib/authenticate/model/email.rb +3 -6
  16. data/lib/authenticate/model/lifetimed.rb +1 -1
  17. data/lib/authenticate/model/password_reset.rb +1 -1
  18. data/lib/authenticate/model/timeoutable.rb +2 -2
  19. data/lib/authenticate/model/trackable.rb +1 -1
  20. data/lib/authenticate/model/username.rb +1 -1
  21. data/lib/authenticate/session.rb +0 -4
  22. data/lib/authenticate/user.rb +12 -0
  23. data/lib/authenticate/version.rb +1 -1
  24. data/spec/controllers/passwords_controller_spec.rb +119 -0
  25. data/spec/controllers/secured_controller_spec.rb +70 -0
  26. data/spec/controllers/sessions_controller_spec.rb +86 -0
  27. data/spec/controllers/users_controller_spec.rb +82 -0
  28. data/spec/dummy/app/controllers/application_controller.rb +2 -0
  29. data/spec/dummy/app/controllers/welcome_controller.rb +4 -0
  30. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  31. data/spec/dummy/app/views/welcome/index.html.erb +4 -0
  32. data/spec/dummy/config/application.rb +2 -0
  33. data/spec/dummy/config/environments/production.rb +12 -0
  34. data/spec/dummy/config/initializers/authenticate.rb +4 -11
  35. data/spec/dummy/config/routes.rb +3 -0
  36. data/spec/dummy/db/test.sqlite3 +0 -0
  37. data/spec/factories/users.rb +2 -4
  38. data/spec/features/brute_force_spec.rb +49 -0
  39. data/spec/features/max_session_lifetime_spec.rb +30 -0
  40. data/spec/features/password_reset_spec.rb +69 -0
  41. data/spec/features/password_update_spec.rb +41 -0
  42. data/spec/features/sign_in_spec.rb +29 -0
  43. data/spec/features/sign_out_spec.rb +22 -0
  44. data/spec/features/sign_up_spec.rb +42 -0
  45. data/spec/features/timeoutable_spec.rb +30 -0
  46. data/spec/model/brute_force_spec.rb +26 -29
  47. data/spec/model/configuration_spec.rb +61 -0
  48. data/spec/model/db_password_spec.rb +8 -9
  49. data/spec/model/email_spec.rb +0 -1
  50. data/spec/model/lifetimed_spec.rb +6 -18
  51. data/spec/model/password_reset_spec.rb +2 -9
  52. data/spec/model/session_spec.rb +16 -23
  53. data/spec/model/timeoutable_spec.rb +8 -7
  54. data/spec/model/trackable_spec.rb +0 -1
  55. data/spec/model/user_spec.rb +1 -2
  56. data/spec/spec_helper.rb +33 -131
  57. data/spec/support/controllers/controller_helpers.rb +24 -0
  58. data/spec/support/features/feature_helpers.rb +36 -0
  59. metadata +80 -8
  60. data/spec/configuration_spec.rb +0 -60
@@ -3,7 +3,6 @@ require 'authenticate/model/email'
3
3
 
4
4
 
5
5
  describe Authenticate::Model::Email do
6
-
7
6
  it 'validates email' do
8
7
  user = build(:user, :without_email)
9
8
  user.save
@@ -3,31 +3,19 @@ require 'authenticate/model/lifetimed'
3
3
 
4
4
 
5
5
  describe Authenticate::Model::Lifetimed do
6
-
7
6
  context '#max_session_lifetime_exceeded?' do
8
- before {
9
- Authenticate.configure do |config|
10
- config.max_session_lifetime = 10.minutes
11
- end
12
- }
13
7
 
14
8
  it 'passes fresh sessions' do
15
- user = create(:user, current_sign_in_at: 1.minute.ago.utc)
16
- expect(user).to_not be_max_session_lifetime_exceeded
9
+ Timecop.freeze do
10
+ user = create(:user, current_sign_in_at: 1.minute.ago.utc)
11
+ expect(user).to_not be_max_session_lifetime_exceeded
12
+ end
17
13
  end
18
14
 
19
15
  it 'detects timed out sessions' do
20
- user = create(:user, current_sign_in_at: 5.hours.ago.utc)
21
- expect(user).to be_max_session_lifetime_exceeded
22
- end
23
-
24
- describe 'max_session_lifetime param not set' do
25
- it 'does not time out' do
16
+ Timecop.freeze do
26
17
  user = create(:user, current_sign_in_at: 5.hours.ago.utc)
27
- Authenticate.configure do |config|
28
- config.max_session_lifetime = nil
29
- end
30
- expect(user).to_not be_max_session_lifetime_exceeded
18
+ expect(user).to be_max_session_lifetime_exceeded
31
19
  end
32
20
  end
33
21
  end
@@ -3,9 +3,6 @@ require 'authenticate/model/password_reset'
3
3
 
4
4
 
5
5
  describe Authenticate::Model::PasswordReset do
6
- before(:all) {
7
- Authenticate.configuration.reset_password_within = 5.minutes
8
- }
9
6
  context 'forgot_password!' do
10
7
  subject { create(:user) }
11
8
  before { subject.forgot_password! }
@@ -22,14 +19,13 @@ describe Authenticate::Model::PasswordReset do
22
19
 
23
20
  context '#reset_password_period_valid?' do
24
21
  subject { create(:user) }
25
- before(:each) {
26
- Authenticate.configuration.reset_password_within = 5.minutes
27
- }
28
22
 
29
23
  it 'always true if reset_password_within config param is nil' do
24
+ within = Authenticate.configuration.reset_password_within
30
25
  subject.password_reset_sent_at = 10.days.ago
31
26
  Authenticate.configuration.reset_password_within = nil
32
27
  expect(subject.reset_password_period_valid?).to be_truthy
28
+ Authenticate.configuration.reset_password_within = within
33
29
  end
34
30
 
35
31
  it 'false if time exceeded' do
@@ -45,9 +41,6 @@ describe Authenticate::Model::PasswordReset do
45
41
 
46
42
  context '#update_password' do
47
43
  subject { create(:user) }
48
- before(:each) {
49
- Authenticate.configuration.reset_password_within = 5.minutes
50
- }
51
44
 
52
45
  context 'within time time' do
53
46
  before(:each) {
@@ -2,24 +2,23 @@ require 'spec_helper'
2
2
 
3
3
 
4
4
  describe Authenticate::Session do
5
-
6
5
  describe 'session token' do
7
6
  it 'finds a user from session token' do
8
7
  user = create(:user, :with_session_token)
9
- request = {}
10
- cookies = {authenticate_session_token: user.session_token}
8
+ request = mock_request
9
+ cookies = cookies_for user
11
10
  session = Authenticate::Session.new(request, cookies)
12
11
  expect(session.current_user).to eq user
13
12
  end
14
- it 'returns nil without a session token' do
15
- request = {}
16
- cookies = {session_token: nil}
13
+ it 'nil user without a session token' do
14
+ request = mock_request
15
+ cookies = {}
17
16
  session = Authenticate::Session.new(request, cookies)
18
17
  expect(session.current_user).to be_nil
19
18
  end
20
19
  it 'returns nil with a bogus session token' do
21
- request = {}
22
- cookies = {session_token: 'some made up value'}
20
+ request = mock_request
21
+ cookies = {Authenticate.configuration.cookie_name.freeze.to_sym => 'some made up value'}
23
22
  session = Authenticate::Session.new(request, cookies)
24
23
  expect(session.current_user).to be_nil
25
24
  end
@@ -27,23 +26,20 @@ describe Authenticate::Session do
27
26
 
28
27
  describe '#login' do
29
28
  it 'sets current_user' do
30
- user = build(:user, :with_session_token)
29
+ user = create(:user)
31
30
  session = Authenticate::Session.new(mock_request, {})
32
31
  session.login(user)
33
32
  expect(session.current_user).to eq user
34
33
  end
35
34
  context 'with a block' do
36
35
  it 'passes the success status to the block when login succeeds' do
37
- user = build(:user, :with_session_token)
36
+ user = create(:user)
38
37
  session = Authenticate::Session.new(mock_request, {})
39
- session.login user do |status|
38
+ session.login(user) do |status|
40
39
  expect(status.success?).to eq true
41
40
  end
42
41
  end
43
42
  it 'passes the failure status to the block when login fails' do
44
- Authenticate.configure do |config|
45
- config.max_consecutive_bad_logins_allowed = nil
46
- end
47
43
  session = Authenticate::Session.new(mock_request, {})
48
44
  session.login nil do |status|
49
45
  expect(status.success?).to eq false
@@ -65,20 +61,17 @@ describe Authenticate::Session do
65
61
  expect{session.login(user)}.to change{user.sign_in_count}.by(1)
66
62
  end
67
63
  it 'fails login if a callback fails' do
68
- failure_message = 'THIS IS A FORCED FAIL'
69
- Authenticate.lifecycle.after_authentication do |user, session, opts|
70
- throw(:failure, failure_message)
71
- end
72
- user = create(:user, :with_session_token, last_access_at: 10.minutes.ago)
73
- cookies = {authenticate_session_token: user.session_token}
64
+ cookies = {}
74
65
  session = Authenticate::Session.new(mock_request, cookies)
75
- session.login user do |status|
66
+ session.login nil do |status|
76
67
  expect(status.success?).to eq false
77
- expect(status.message).to eq failure_message
68
+ expect(status.message).to eq I18n.t('callbacks.authenticatable.failure')
78
69
  end
79
70
  end
80
71
  end
81
72
  end
73
+ end
82
74
 
83
-
75
+ def cookies_for user
76
+ { Authenticate.configuration.cookie_name.freeze.to_sym => user.session_token }
84
77
  end
@@ -3,18 +3,19 @@ require 'authenticate/model/timeoutable'
3
3
 
4
4
 
5
5
  describe Authenticate::Model::Timeoutable do
6
- before(:all) {
7
- Authenticate.configuration.timeout_in = 45.minutes
8
- }
9
6
  subject { create(:user) }
10
7
 
11
8
  it 'does not timeout while last_access_at is valid' do
12
- subject.last_access_at = 10.minutes.ago
13
- expect(subject.timedout?).to be_falsey
9
+ Timecop.freeze do
10
+ subject.last_access_at = 10.minutes.ago
11
+ expect(subject.timedout?).to be_falsey
12
+ end
14
13
  end
15
14
 
16
15
  it 'does timeout when last_access_at is stale' do
17
- subject.last_access_at = 46.minutes.ago
18
- expect(subject.timedout?).to be_truthy
16
+ Timecop.freeze do
17
+ subject.last_access_at = 46.minutes.ago
18
+ expect(subject.timedout?).to be_truthy
19
+ end
19
20
  end
20
21
  end
@@ -4,7 +4,6 @@ require 'authenticate/model/trackable'
4
4
 
5
5
  describe Authenticate::Model::Trackable do
6
6
  subject {create(:user)}
7
-
8
7
  context '#last_sign_in_at' do
9
8
  it 'sets to old current_sign_in_at if it is not nil' do
10
9
  old_sign_in = 2.days.ago.utc
@@ -1,7 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Authenticate::User do
4
-
5
4
  context 'session tokens' do
6
5
  it 'generates a new session token' do
7
6
  user = create(:user, :with_session_token)
@@ -19,4 +18,4 @@ describe Authenticate::User do
19
18
  end
20
19
  end
21
20
 
22
- end
21
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,56 +1,52 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ ENV['RAILS_ENV'] ||= 'test'
3
3
 
4
-
5
- ENV["RAILS_ENV"] ||= 'test'
6
-
7
- MY_ORM = :active_record
8
-
9
- # require 'simplecov'
10
- # SimpleCov.root File.join(File.dirname(__FILE__), '..', 'lib')
11
- # SimpleCov.start
12
-
13
-
14
- require 'rails/all'
4
+ require File.expand_path('../dummy/config/environment.rb', __FILE__)
15
5
  require 'rspec/rails'
16
- require 'factory_girl_rails'
17
- # require 'timecop'
18
-
19
- require 'authenticate'
6
+ require 'shoulda-matchers'
7
+ require 'capybara/rails'
8
+ require 'capybara/rspec'
9
+ require 'database_cleaner'
10
+ require 'factory_girl'
11
+ require 'timecop'
20
12
 
21
- ENGINE_RAILS_ROOT=File.join(File.dirname(__FILE__), '../')
22
- Dir[File.join(ENGINE_RAILS_ROOT, "spec/factories/**/*.rb")].each {|f| require f }
13
+ Rails.backtrace_cleaner.remove_silencers!
14
+ DatabaseCleaner.strategy = :truncation
23
15
 
24
- def setup_orm; end
25
- def teardown_orm; end
26
-
27
- require "orm/#{MY_ORM}"
16
+ # No longer autoloading support, individually requiring instead.
17
+ #
18
+ # Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
28
19
 
29
- # require "rails_app/config/environment"
30
- require "dummy/config/environment"
20
+ # Load factory girl factories.
21
+ Dir[File.join(File.dirname(__FILE__), 'factories/**/*.rb')].each { |f| require f }
31
22
 
32
- # class TestMailer < ActionMailer::Base;end
23
+ RSpec.configure do |config|
24
+ config.include FactoryGirl::Syntax::Methods
25
+ config.infer_spec_type_from_file_location!
26
+ config.order = :random
27
+ config.use_transactional_fixtures = true
33
28
 
34
- Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
29
+ # config.mock_with :rspec
35
30
 
36
- RSpec.configure do |config|
37
- config.fixture_path = "#{::Rails.root}/spec/factories"
31
+ config.expect_with :rspec do |expectations|
32
+ expectations.syntax = :expect
33
+ end
38
34
 
39
- config.include RSpec::Rails::ControllerExampleGroup, :file_path => /controller(.)*_spec.rb$/
40
- config.mock_with :rspec
41
- config.include FactoryGirl::Syntax::Methods
35
+ config.mock_with :rspec do |mocks|
36
+ mocks.syntax = :expect
37
+ end
42
38
 
43
- config.use_transactional_fixtures = true
44
39
 
45
- config.before(:suite) { setup_orm }
46
- config.after(:suite) { teardown_orm }
47
- config.before(:each) { ActionMailer::Base.deliveries.clear }
40
+ config.after(:each, :type => :feature) do
41
+ DatabaseCleaner.clean # Truncate the database
42
+ Capybara.reset_sessions! # Forget the (simulated) browser state
43
+ Capybara.use_default_driver # Revert Capybara.current_driver to Capybara.default_driver
44
+ end
48
45
  end
49
46
 
50
47
 
51
48
  def restore_default_configuration
52
- Authenticate.configuration = nil
53
- Authenticate.configure {}
49
+ puts 'restore_default_configuration called!!!!!!!!!!!!!!!!!!!!!'
54
50
  end
55
51
 
56
52
  def mock_request(params = {})
@@ -59,97 +55,3 @@ def mock_request(params = {})
59
55
  allow(req).to receive(:remote_ip).and_return('111.111.111.111')
60
56
  req
61
57
  end
62
-
63
-
64
- # # This file was generated by the `rails generate rspec:install` command. Conventionally, all
65
- # # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
66
- # # The generated `.rspec` file contains `--require spec_helper` which will cause
67
- # # this file to always be loaded, without a need to explicitly require it in any
68
- # # files.
69
- # #
70
- # # Given that it is always loaded, you are encouraged to keep this file as
71
- # # light-weight as possible. Requiring heavyweight dependencies from this file
72
- # # will add to the boot time of your test suite on EVERY test run, even for an
73
- # # individual file that may not need all of that loaded. Instead, consider making
74
- # # a separate helper file that requires the additional dependencies and performs
75
- # # the additional setup, and require it from the spec files that actually need
76
- # # it.
77
- # #
78
- # # The `.rspec` file also contains a few flags that are not defaults but that
79
- # # users commonly want.
80
- # #
81
- # # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
82
- # RSpec.configure do |config|
83
- # # rspec-expectations config goes here. You can use an alternate
84
- # # assertion/expectation library such as wrong or the stdlib/minitest
85
- # # assertions if you prefer.
86
- # config.expect_with :rspec do |expectations|
87
- # # This option will default to `true` in RSpec 4. It makes the `description`
88
- # # and `failure_message` of custom matchers include text for helper methods
89
- # # defined using `chain`, e.g.:
90
- # # be_bigger_than(2).and_smaller_than(4).description
91
- # # # => "be bigger than 2 and smaller than 4"
92
- # # ...rather than:
93
- # # # => "be bigger than 2"
94
- # expectations.include_chain_clauses_in_custom_matcher_descriptions = true
95
- # end
96
- #
97
- # # rspec-mocks config goes here. You can use an alternate test double
98
- # # library (such as bogus or mocha) by changing the `mock_with` option here.
99
- # config.mock_with :rspec do |mocks|
100
- # # Prevents you from mocking or stubbing a method that does not exist on
101
- # # a real object. This is generally recommended, and will default to
102
- # # `true` in RSpec 4.
103
- # mocks.verify_partial_doubles = true
104
- # end
105
- #
106
- # # The settings below are suggested to provide a good initial experience
107
- # # with RSpec, but feel free to customize to your heart's content.
108
- # =begin
109
- # # These two settings work together to allow you to limit a spec run
110
- # # to individual examples or groups you care about by tagging them with
111
- # # `:focus` metadata. When nothing is tagged with `:focus`, all examples
112
- # # get run.
113
- # config.filter_run :focus
114
- # config.run_all_when_everything_filtered = true
115
- #
116
- # # Allows RSpec to persist some state between runs in order to support
117
- # # the `--only-failures` and `--next-failure` CLI options. We recommend
118
- # # you configure your source control system to ignore this file.
119
- # config.example_status_persistence_file_path = "spec/examples.txt"
120
- #
121
- # # Limits the available syntax to the non-monkey patched syntax that is
122
- # # recommended. For more details, see:
123
- # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
124
- # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
125
- # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
126
- # config.disable_monkey_patching!
127
- #
128
- # # Many RSpec users commonly either run the entire suite or an individual
129
- # # file, and it's useful to allow more verbose output when running an
130
- # # individual spec file.
131
- # if config.files_to_run.one?
132
- # # Use the documentation formatter for detailed output,
133
- # # unless a formatter has already been configured
134
- # # (e.g. via a command-line flag).
135
- # config.default_formatter = 'doc'
136
- # end
137
- #
138
- # # Print the 10 slowest examples and example groups at the
139
- # # end of the spec run, to help surface which specs are running
140
- # # particularly slow.
141
- # config.profile_examples = 10
142
- #
143
- # # Run specs in random order to surface order dependencies. If you find an
144
- # # order dependency and want to debug it, you can fix the order by providing
145
- # # the seed, which is printed after each run.
146
- # # --seed 1234
147
- # config.order = :random
148
- #
149
- # # Seed global randomization in this process using the `--seed` CLI option.
150
- # # Setting this allows you to use `--seed` to deterministically reproduce
151
- # # test failures related to randomization by passing the same `--seed` value
152
- # # as the one that triggered the failure.
153
- # Kernel.srand config.seed
154
- # =end
155
- # end
@@ -0,0 +1,24 @@
1
+ require 'authenticate/controller'
2
+
3
+ module Controllers
4
+ module ControllerHelpers
5
+
6
+ def sign_in
7
+ user = create(:user)
8
+ sign_in_as user
9
+ end
10
+
11
+ def sign_in_as(user)
12
+ controller.login user
13
+ end
14
+
15
+ def sign_out
16
+ controller.logout
17
+ end
18
+
19
+ end
20
+ end
21
+
22
+ RSpec.configure do |config|
23
+ config.include Controllers::ControllerHelpers, type: :controller
24
+ end
@@ -0,0 +1,36 @@
1
+ module Features
2
+ module FeatureHelpers
3
+
4
+
5
+ def sign_in_with(email, password)
6
+ visit sign_in_path
7
+ fill_in 'session_email', with: email
8
+ fill_in 'session_password', with: password
9
+ click_button 'Sign in'
10
+ end
11
+
12
+ def sign_out
13
+ within '#header' do
14
+ click_link I18n.t("layouts.application.sign_out")
15
+ end
16
+ end
17
+
18
+ def expect_user_to_be_signed_in
19
+ visit root_path
20
+ expect(page).to have_link 'Sign out'
21
+ end
22
+
23
+ def expect_page_to_display_sign_in_error
24
+ expect(page).to have_content 'Invalid id or password'
25
+ end
26
+
27
+ def expect_user_to_be_signed_out
28
+ expect(page).to have_content 'Sign in'
29
+ end
30
+
31
+ end
32
+ end
33
+
34
+ RSpec.configure do |config|
35
+ config.include Features::FeatureHelpers, type: :feature
36
+ end