sorcery 0.1.3 → 0.1.4

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

Potentially problematic release.


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

Files changed (36) hide show
  1. data/Gemfile +1 -2
  2. data/LICENSE.txt +1 -1
  3. data/README.rdoc +27 -11
  4. data/Rakefile +2 -13
  5. data/VERSION +1 -1
  6. data/lib/sorcery.rb +4 -1
  7. data/lib/sorcery/controller.rb +13 -7
  8. data/lib/sorcery/controller/submodules/activity_logging.rb +45 -0
  9. data/lib/sorcery/controller/submodules/brute_force_protection.rb +8 -69
  10. data/lib/sorcery/controller/submodules/http_basic_auth.rb +7 -4
  11. data/lib/sorcery/controller/submodules/session_timeout.rb +4 -1
  12. data/lib/sorcery/crypto_providers/bcrypt.rb +1 -5
  13. data/lib/sorcery/model/submodules/activity_logging.rb +35 -0
  14. data/lib/sorcery/model/submodules/brute_force_protection.rb +72 -0
  15. data/lib/sorcery/model/submodules/remember_me.rb +3 -1
  16. data/lib/sorcery/model/submodules/reset_password.rb +93 -0
  17. data/lib/sorcery/model/submodules/user_activation.rb +2 -0
  18. data/sorcery.gemspec +26 -14
  19. data/spec/rails3/app_root/app/controllers/application_controller.rb +2 -2
  20. data/spec/rails3/app_root/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +17 -0
  21. data/spec/rails3/app_root/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +11 -0
  22. data/spec/rails3/app_root/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +13 -0
  23. data/spec/rails3/controller_activity_logging_spec.rb +84 -0
  24. data/spec/rails3/controller_brute_force_protection_spec.rb +24 -41
  25. data/spec/rails3/controller_http_basic_auth_spec.rb +10 -0
  26. data/spec/rails3/controller_session_timeout_spec.rb +1 -0
  27. data/spec/rails3/controller_spec.rb +3 -3
  28. data/spec/rails3/spec_helper.rb +39 -19
  29. data/spec/rails3/user_activity_logging_spec.rb +36 -0
  30. data/spec/rails3/user_brute_force_protection_spec.rb +76 -0
  31. data/spec/rails3/user_reset_password_spec.rb +198 -0
  32. metadata +34 -22
  33. data/features/support/env.rb +0 -13
  34. data/lib/sorcery/model/submodules/password_reset.rb +0 -64
  35. data/spec/rails3/app_root/db/migrate/password_reset/20101224223622_add_password_reset_to_users.rb +0 -9
  36. data/spec/rails3/user_password_reset_spec.rb +0 -76
@@ -1,6 +1,13 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe ApplicationController do
4
+ before(:all) do
5
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/brute_force_protection")
6
+ end
7
+
8
+ after(:all) do
9
+ ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/brute_force_protection")
10
+ end
4
11
 
5
12
  # ----------------- SESSION TIMEOUT -----------------------
6
13
  describe ApplicationController, "with brute force protection features" do
@@ -14,59 +21,35 @@ describe ApplicationController do
14
21
  plugin_set_controller_config_property(:user_class, User)
15
22
  end
16
23
 
17
- it "should have configuration for 'login_retries_amount_allowed' per session" do
18
- plugin_set_controller_config_property(:login_retries_amount_allowed, 32)
19
- Sorcery::Controller::Config.login_retries_amount_allowed.should equal(32)
20
- end
21
-
22
- it "should have configuration for 'login_retries_counter_reset_time'" do
23
- plugin_set_controller_config_property(:login_retries_time_period, 32)
24
- Sorcery::Controller::Config.login_retries_time_period.should equal(32)
25
- end
26
-
27
- it "should count login retries per session" do
24
+ it "should count login retries" do
28
25
  3.times {get :test_login, :username => 'gizmo', :password => 'blabla'}
29
- session[:failed_logins].should == 3
26
+ User.find_by_username('gizmo').failed_logins_count.should == 3
30
27
  end
31
28
 
32
- it "should reset the counter if enough time has passed" do
33
- plugin_set_controller_config_property(:login_retries_amount_allowed, 5)
34
- plugin_set_controller_config_property(:login_retries_time_period, 0.2)
35
- get :test_login, :username => 'gizmo', :password => 'blabla'
36
- sleep 0.4
37
- get :test_login, :username => 'gizmo', :password => 'blabla'
38
- session[:failed_logins].should == 1
29
+ it "should reset the counter on a good login" do
30
+ plugin_set_model_config_property(:consecutive_login_retries_amount_allowed, 5)
31
+ 3.times {get :test_login, :username => 'gizmo', :password => 'blabla'}
32
+ get :test_login, :username => 'gizmo', :password => 'secret'
33
+ User.find_by_username('gizmo').failed_logins_count.should == 0
39
34
  end
40
35
 
41
- it "should ban session when number of retries reached within an amount of time" do
42
- plugin_set_controller_config_property(:login_retries_amount_allowed, 1)
43
- plugin_set_controller_config_property(:login_retries_time_period, 50)
44
- get :test_login, :username => 'gizmo', :password => 'blabla'
36
+ it "should lock user when number of retries reached the limit" do
37
+ User.find_by_username('gizmo').lock_expires_at.should be_nil
38
+ plugin_set_model_config_property(:consecutive_login_retries_amount_allowed, 1)
45
39
  get :test_login, :username => 'gizmo', :password => 'blabla'
46
- session[:banned].should == true
40
+ User.find_by_username('gizmo').lock_expires_at.should_not be_nil
47
41
  end
48
42
 
49
- it "should clear ban after ban time limit passes" do
50
- plugin_set_controller_config_property(:login_retries_amount_allowed, 1)
51
- plugin_set_controller_config_property(:login_retries_time_period, 50)
52
- plugin_set_controller_config_property(:login_ban_time_period, 0.2)
43
+ it "should unlock after lock time period passes" do
44
+ plugin_set_model_config_property(:consecutive_login_retries_amount_allowed, 2)
45
+ plugin_set_model_config_property(:login_lock_time_period, 0.2)
53
46
  get :test_login, :username => 'gizmo', :password => 'blabla'
54
47
  get :test_login, :username => 'gizmo', :password => 'blabla'
55
- session[:banned].should == true
48
+ User.find_by_username('gizmo').lock_expires_at.should_not be_nil
56
49
  sleep 0.3
57
50
  get :test_login, :username => 'gizmo', :password => 'blabla'
58
- session[:banned].should == nil
59
- end
60
-
61
- it "banned session calls the configured banned action" do
62
- plugin_set_controller_config_property(:login_retries_amount_allowed, 1)
63
- plugin_set_controller_config_property(:login_retries_time_period, 50)
64
- plugin_set_controller_config_property(:login_ban_time_period, 50)
65
- get :test_login, :username => 'gizmo', :password => 'blabla'
66
- get :test_login, :username => 'gizmo', :password => 'blabla'
67
- get :test_login, :username => 'gizmo', :password => 'blabla'
68
- session[:banned].should == true
69
- response.body.should == " "
51
+ User.find_by_username('gizmo').lock_expires_at.should be_nil
70
52
  end
53
+
71
54
  end
72
55
  end
@@ -9,6 +9,10 @@ describe ApplicationController do
9
9
  create_new_user
10
10
  end
11
11
 
12
+ after(:each) do
13
+ logout_user
14
+ end
15
+
12
16
  it "requests basic authentication when before_filter is used" do
13
17
  get :test_http_basic_auth
14
18
  response.code.should == "401"
@@ -36,5 +40,11 @@ describe ApplicationController do
36
40
  get :test_http_basic_auth
37
41
  response.headers["WWW-Authenticate"].should == "Basic realm=\"Salad\""
38
42
  end
43
+
44
+ it "should sign in the user's session on successful login" do
45
+ @request.env["HTTP_AUTHORIZATION"] = "Basic " + Base64::encode64("#{@user.username}:secret")
46
+ get :test_http_basic_auth, nil, :http_authentication_used => true
47
+ session[:user_id].should == User.find_by_username(@user.username).id
48
+ end
39
49
  end
40
50
  end
@@ -45,5 +45,6 @@ describe ApplicationController do
45
45
  session[:user_id].should be_nil
46
46
  response.should be_a_redirect
47
47
  end
48
+
48
49
  end
49
50
  end
@@ -93,8 +93,8 @@ describe ApplicationController do
93
93
  subject.logged_in_user.should == false
94
94
  end
95
95
 
96
- it "should respond to 'require_user_login'" do
97
- should respond_to(:require_user_login)
96
+ it "should respond to 'require_login'" do
97
+ should respond_to(:require_login)
98
98
  end
99
99
 
100
100
  it "should call the configured 'not_authenticated_action' when authenticate before_filter fails" do
@@ -104,7 +104,7 @@ describe ApplicationController do
104
104
  response.body.should == "test_not_authenticated_action"
105
105
  end
106
106
 
107
- it "require_user_login before_filter should save the url that the user originally wanted" do
107
+ it "require_login before_filter should save the url that the user originally wanted" do
108
108
  get :some_action
109
109
  session[:user_wanted_url].should == "http://test.host/some_action"
110
110
  response.should redirect_to("http://test.host/")
@@ -1,17 +1,17 @@
1
1
  $: << File.join(File.dirname(__FILE__), '..', '..', 'lib' )
2
2
 
3
- require 'simplecov'
4
- SimpleCov.root File.join(File.dirname(__FILE__), "app_root" )
5
- SimpleCov.start do
6
- add_filter "/config/"
7
-
8
- add_group 'Controllers', 'app/controllers'
9
- add_group 'Models', 'app/models'
10
- add_group 'Helpers', 'app/helpers'
11
- add_group 'Libraries', 'lib'
12
- add_group 'Plugins', 'vendor/plugins'
13
- add_group 'Migrations', 'db/migrate'
14
- end
3
+ # require 'simplecov'
4
+ # SimpleCov.root File.join(File.dirname(__FILE__), "app_root" )
5
+ # SimpleCov.start do
6
+ # add_filter "/config/"
7
+ #
8
+ # add_group 'Controllers', 'app/controllers'
9
+ # add_group 'Models', 'app/models'
10
+ # add_group 'Helpers', 'app/helpers'
11
+ # add_group 'Libraries', 'lib'
12
+ # add_group 'Plugins', 'vendor/plugins'
13
+ # add_group 'Migrations', 'db/migrate'
14
+ # end
15
15
 
16
16
  # Set the default environment to sqlite3's in_memory database
17
17
  ENV['RAILS_ENV'] ||= 'in_memory'
@@ -41,7 +41,8 @@ RSpec.configure do |config|
41
41
  end
42
42
 
43
43
  #----------------------------------------------------------------
44
- #require File.join(File.dirname(__FILE__), 'app_root','app','models','user')
44
+ # needed when running individual specs
45
+ require File.join(File.dirname(__FILE__), 'app_root','app','models','user')
45
46
 
46
47
  class TestUser < ActiveRecord::Base
47
48
  activate_sorcery!
@@ -62,15 +63,27 @@ module Sorcery
62
63
  end
63
64
  end
64
65
 
65
- def create_new_user
66
- user_attributes_hash = {:username => 'gizmo', :email => "bla@bla.com", :password => 'secret'}
66
+ SUBMODUELS_AUTO_ADDED_CONTROLLER_FILTERS = [:register_last_activity_time_to_db, :deny_banned_user, :validate_session]
67
+
68
+ def create_new_user(attributes_hash = nil)
69
+ user_attributes_hash = attributes_hash || {:username => 'gizmo', :email => "bla@bla.com", :password => 'secret'}
67
70
  @user = User.new(user_attributes_hash)
68
71
  @user.save!
72
+ @user
73
+ end
74
+
75
+ def login_user(user = nil)
76
+ user ||= @user
77
+ subject.send(:login_user,user)
78
+ subject.send(:after_login!,user,[user.username,'secret'])
79
+ end
80
+
81
+ def logout_user
82
+ subject.send(:logout)
69
83
  end
70
84
 
71
- def login_user
72
- subject.send(:login_user,@user)
73
- subject.send(:after_login!,@user,['gizmo','secret'])
85
+ def clear_user_without_logout
86
+ subject.instance_variable_set(:@logged_in_user,nil)
74
87
  end
75
88
 
76
89
  # TODO: rename to sorcery_reload!(subs = [], model_opts = {}, controller_opts = {})
@@ -81,10 +94,15 @@ def plugin_model_configure(submodules = [], options = {})
81
94
  ::Sorcery::Controller::Config.init!
82
95
  ::Sorcery::Controller::Config.reset!
83
96
 
97
+ # remove all plugin before_filters so they won't fail other tests.
98
+ # I don't like this way, but I didn't find another.
99
+ # hopefully it won't break until Rails 4.
100
+ ApplicationController._process_action_callbacks.delete_if {|c| SUBMODUELS_AUTO_ADDED_CONTROLLER_FILTERS.include?(c.filter) }
101
+
84
102
  # configure
85
103
  ::Sorcery::Controller::Config.submodules = submodules
86
104
  ::Sorcery::Controller::Config.user_class = nil # the next line will reset it to User
87
- ApplicationController.send(:include,::Sorcery::Controller)
105
+ ActionController::Base.send(:include,::Sorcery::Controller)
88
106
 
89
107
  User.activate_sorcery! do |config|
90
108
  options.each do |property,value|
@@ -109,6 +127,8 @@ end
109
127
 
110
128
  private
111
129
 
130
+ # reload user class between specs
131
+ # so it will be possible to test the different submodules in isolation
112
132
  def reload_user_class
113
133
  Object.send(:remove_const,:User)
114
134
  load 'user.rb'
@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "User with activity logging submodule" do
4
+ before(:all) do
5
+ end
6
+
7
+ after(:all) do
8
+ end
9
+
10
+ # ----------------- PLUGIN CONFIGURATION -----------------------
11
+ describe User, "loaded plugin configuration" do
12
+ before(:all) do
13
+ plugin_model_configure([:activity_logging])
14
+ end
15
+
16
+ after(:each) do
17
+ User.sorcery_config.reset!
18
+ end
19
+
20
+ it "should allow configuration option 'last_login_at_attribute_name'" do
21
+ plugin_set_model_config_property(:last_login_at_attribute_name, :login_time)
22
+ User.sorcery_config.last_login_at_attribute_name.should equal(:login_time)
23
+ end
24
+
25
+ it "should allow configuration option 'last_logout_at_attribute_name'" do
26
+ plugin_set_model_config_property(:last_logout_at_attribute_name, :logout_time)
27
+ User.sorcery_config.last_logout_at_attribute_name.should equal(:logout_time)
28
+ end
29
+
30
+ it "should allow configuration option 'last_activity_at_attribute_name'" do
31
+ plugin_set_model_config_property(:last_activity_at_attribute_name, :activity_time)
32
+ User.sorcery_config.last_activity_at_attribute_name.should equal(:activity_time)
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,76 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "User with brute_force_protection submodule" do
4
+ before(:all) do
5
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/brute_force_protection")
6
+ end
7
+
8
+ after(:all) do
9
+ ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/brute_force_protection")
10
+ end
11
+
12
+ # ----------------- PLUGIN CONFIGURATION -----------------------
13
+ describe User, "loaded plugin configuration" do
14
+
15
+ before(:all) do
16
+ plugin_model_configure([:brute_force_protection])
17
+ create_new_user
18
+ end
19
+
20
+ after(:each) do
21
+ User.sorcery_config.reset!
22
+ end
23
+
24
+ it "should respond to 'failed_logins_count'" do
25
+ @user.should respond_to(:failed_logins_count)
26
+ end
27
+
28
+ it "should respond to 'lock_expires_at'" do
29
+ @user.should respond_to(:failed_logins_count)
30
+ end
31
+
32
+ it "should enable configuration option 'failed_logins_count_attribute_name'" do
33
+ plugin_set_model_config_property(:failed_logins_count_attribute_name, :my_count)
34
+ User.sorcery_config.failed_logins_count_attribute_name.should equal(:my_count)
35
+ end
36
+
37
+ it "should enable configuration option 'lock_expires_at_attribute_name'" do
38
+ plugin_set_model_config_property(:lock_expires_at_attribute_name, :expires)
39
+ User.sorcery_config.lock_expires_at_attribute_name.should equal(:expires)
40
+ end
41
+
42
+ it "should enable configuration option 'consecutive_login_retries_amount_allowed'" do
43
+ plugin_set_model_config_property(:consecutive_login_retries_amount_allowed, 34)
44
+ User.sorcery_config.consecutive_login_retries_amount_allowed.should equal(34)
45
+ end
46
+
47
+ it "should enable configuration option 'login_lock_time_period'" do
48
+ plugin_set_model_config_property(:login_lock_time_period, 2.hours)
49
+ User.sorcery_config.login_lock_time_period.should == 2.hours
50
+ end
51
+ end
52
+
53
+ # ----------------- PLUGIN ACTIVATED -----------------------
54
+ describe User, "when activated with sorcery" do
55
+
56
+ before(:all) do
57
+ plugin_model_configure([:brute_force_protection])
58
+ end
59
+
60
+ before(:each) do
61
+ User.delete_all
62
+ end
63
+
64
+ # it "should increment failed_logins_count on a failed login" do
65
+ # create_new_user
66
+ #
67
+ # end
68
+ #
69
+ # it "should set lock expiry (effectively lock user) when failed_logins_count reaches max within max period" do
70
+ # create_new_user
71
+ # @user.lock_expires_at.should == Time.now.utc + 30
72
+ # end
73
+
74
+ end
75
+
76
+ end
@@ -0,0 +1,198 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "User with reset_password submodule" do
4
+ before(:all) do
5
+ ActiveRecord::Migrator.migrate("#{Rails.root}/db/migrate/reset_password")
6
+ end
7
+
8
+ after(:all) do
9
+ ActiveRecord::Migrator.rollback("#{Rails.root}/db/migrate/reset_password")
10
+ end
11
+
12
+ # ----------------- PLUGIN CONFIGURATION -----------------------
13
+ describe User, "loaded plugin configuration" do
14
+
15
+ before(:all) do
16
+ plugin_model_configure([:reset_password], :reset_password_mailer => ::SorceryMailer)
17
+ end
18
+
19
+ after(:each) do
20
+ User.sorcery_config.reset!
21
+ end
22
+
23
+ it "should respond to 'deliver_reset_password_instructions!'" do
24
+ create_new_user
25
+ @user.should respond_to(:deliver_reset_password_instructions!)
26
+ end
27
+
28
+ it "should respond to 'reset_password_token_valid?'" do
29
+ create_new_user
30
+ @user.should respond_to(:reset_password_token_valid?)
31
+ end
32
+
33
+ it "should respond to 'reset_password!" do
34
+ create_new_user
35
+ @user.should respond_to(:reset_password!)
36
+ end
37
+
38
+ it "should respond to 'load_from_reset_password_token'" do
39
+ create_new_user
40
+ User.should respond_to(:load_from_reset_password_token)
41
+ end
42
+
43
+ it "should allow configuration option 'reset_password_token_attribute_name'" do
44
+ plugin_set_model_config_property(:reset_password_token_attribute_name, :my_code)
45
+ User.sorcery_config.reset_password_token_attribute_name.should equal(:my_code)
46
+ end
47
+
48
+ it "should allow configuration option 'reset_password_mailer'" do
49
+ plugin_set_model_config_property(:reset_password_mailer, TestUser)
50
+ User.sorcery_config.reset_password_mailer.should equal(TestUser)
51
+ end
52
+
53
+ it "should allow configuration option 'reset_password_email_method_name'" do
54
+ plugin_set_model_config_property(:reset_password_email_method_name, :my_mailer_method)
55
+ User.sorcery_config.reset_password_email_method_name.should equal(:my_mailer_method)
56
+ end
57
+
58
+ it "should allow configuration option 'reset_password_expiration_period'" do
59
+ plugin_set_model_config_property(:reset_password_expiration_period, 16)
60
+ User.sorcery_config.reset_password_expiration_period.should equal(16)
61
+ end
62
+
63
+ it "should allow configuration option 'reset_password_email_sent_at_attribute_name'" do
64
+ plugin_set_model_config_property(:reset_password_email_sent_at_attribute_name, :blabla)
65
+ User.sorcery_config.reset_password_email_sent_at_attribute_name.should equal(:blabla)
66
+ end
67
+
68
+ it "should allow configuration option 'reset_password_time_between_emails'" do
69
+ plugin_set_model_config_property(:reset_password_time_between_emails, 16)
70
+ User.sorcery_config.reset_password_time_between_emails.should equal(16)
71
+ end
72
+ end
73
+
74
+ # ----------------- PLUGIN ACTIVATED -----------------------
75
+ describe User, "when activated with sorcery" do
76
+
77
+ before(:all) do
78
+ plugin_model_configure([:reset_password], :reset_password_mailer => ::SorceryMailer)
79
+ end
80
+
81
+ before(:each) do
82
+ User.delete_all
83
+ end
84
+
85
+ it "load_from_reset_password_token should return user when token is found" do
86
+ create_new_user
87
+ @user.deliver_reset_password_instructions!
88
+ User.load_from_reset_password_token(@user.reset_password_token).should == @user
89
+ end
90
+
91
+ it "load_from_reset_password_token should NOT return user when token is NOT found" do
92
+ create_new_user
93
+ @user.deliver_reset_password_instructions!
94
+ User.load_from_reset_password_token("a").should == nil
95
+ end
96
+
97
+ it "load_from_reset_password_token should return user when token is found and not expired" do
98
+ create_new_user
99
+ plugin_set_model_config_property(:reset_password_expiration_period, 500)
100
+ @user.deliver_reset_password_instructions!
101
+ User.load_from_reset_password_token(@user.reset_password_token).should == @user
102
+ end
103
+
104
+ it "load_from_reset_password_token should NOT return user when token is found and expired" do
105
+ create_new_user
106
+ plugin_set_model_config_property(:reset_password_expiration_period, 0.1)
107
+ @user.deliver_reset_password_instructions!
108
+ sleep 0.5
109
+ User.load_from_reset_password_token(@user.reset_password_token).should == nil
110
+ end
111
+
112
+ it "load_from_reset_password_token should return nil if token is blank" do
113
+ User.load_from_reset_password_token(nil).should == nil
114
+ User.load_from_reset_password_token("").should == nil
115
+ end
116
+
117
+ it "'deliver_reset_password_instructions!' should generate a reset_password_token" do
118
+ create_new_user
119
+ @user.reset_password_token.should be_nil
120
+ @user.deliver_reset_password_instructions!
121
+ @user.reset_password_token.should_not be_nil
122
+ end
123
+
124
+ it "the reset_password_token should be random" do
125
+ create_new_user
126
+ plugin_set_model_config_property(:reset_password_time_between_emails, 0)
127
+ @user.deliver_reset_password_instructions!
128
+ old_password_code = @user.reset_password_token
129
+ @user.deliver_reset_password_instructions!
130
+ @user.reset_password_token.should_not == old_password_code
131
+ end
132
+
133
+ it "should send an email on reset" do
134
+ create_new_user
135
+ old_size = ActionMailer::Base.deliveries.size
136
+ @user.deliver_reset_password_instructions!
137
+ ActionMailer::Base.deliveries.size.should == old_size + 1
138
+ end
139
+
140
+ it "when reset_password! is called, should delete reset_password_token" do
141
+ create_new_user
142
+ @user.deliver_reset_password_instructions!
143
+ @user.reset_password_token.should_not be_nil
144
+ @user.reset_password!(:password => "blabulsdf")
145
+ @user.save!
146
+ @user.reset_password_token.should be_nil
147
+ end
148
+
149
+ it "code isn't valid if expiration passed" do
150
+ create_new_user
151
+ plugin_set_model_config_property(:reset_password_expiration_period, 0.1)
152
+ @user.deliver_reset_password_instructions!
153
+ sleep 0.5
154
+ @user.reset_password_token_valid?.should == false
155
+ end
156
+
157
+ it "code is valid if it's the same code and expiration period did not pass" do
158
+ create_new_user
159
+ plugin_set_model_config_property(:reset_password_expiration_period, 300)
160
+ @user.deliver_reset_password_instructions!
161
+ @user.reset_password_token_valid?.should == true
162
+ end
163
+
164
+ it "code is valid if it's the same code and expiration period is nil" do
165
+ create_new_user
166
+ plugin_set_model_config_property(:reset_password_expiration_period, nil)
167
+ @user.deliver_reset_password_instructions!
168
+ @user.reset_password_token_valid?.should == true
169
+ end
170
+
171
+ it "should not send an email if time between emails has not passed since last email" do
172
+ create_new_user
173
+ plugin_set_model_config_property(:reset_password_time_between_emails, 10000)
174
+ old_size = ActionMailer::Base.deliveries.size
175
+ @user.deliver_reset_password_instructions!
176
+ ActionMailer::Base.deliveries.size.should == old_size + 1
177
+ @user.deliver_reset_password_instructions!
178
+ ActionMailer::Base.deliveries.size.should == old_size + 1
179
+ end
180
+
181
+ it "should send an email if time between emails has passed since last email" do
182
+ create_new_user
183
+ plugin_set_model_config_property(:reset_password_time_between_emails, 0.5)
184
+ old_size = ActionMailer::Base.deliveries.size
185
+ @user.deliver_reset_password_instructions!
186
+ ActionMailer::Base.deliveries.size.should == old_size + 1
187
+ sleep 0.5
188
+ @user.deliver_reset_password_instructions!
189
+ ActionMailer::Base.deliveries.size.should == old_size + 2
190
+ end
191
+
192
+ it "if mailer is nil on activation, throw exception!" do
193
+ expect{plugin_model_configure([:reset_password])}.to raise_error(ArgumentError)
194
+ end
195
+
196
+ end
197
+
198
+ end