cbsorcery 0.8.6

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 (135) hide show
  1. data/.document +5 -0
  2. data/.gitignore +56 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +40 -0
  5. data/CHANGELOG.md +263 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE.txt +20 -0
  8. data/README.md +360 -0
  9. data/Rakefile +6 -0
  10. data/gemfiles/active_record-rails40.gemfile +7 -0
  11. data/gemfiles/active_record-rails41.gemfile +7 -0
  12. data/lib/generators/sorcery/USAGE +22 -0
  13. data/lib/generators/sorcery/helpers.rb +40 -0
  14. data/lib/generators/sorcery/install_generator.rb +95 -0
  15. data/lib/generators/sorcery/templates/initializer.rb +451 -0
  16. data/lib/generators/sorcery/templates/migration/activity_logging.rb +10 -0
  17. data/lib/generators/sorcery/templates/migration/brute_force_protection.rb +9 -0
  18. data/lib/generators/sorcery/templates/migration/core.rb +13 -0
  19. data/lib/generators/sorcery/templates/migration/external.rb +12 -0
  20. data/lib/generators/sorcery/templates/migration/remember_me.rb +8 -0
  21. data/lib/generators/sorcery/templates/migration/reset_password.rb +9 -0
  22. data/lib/generators/sorcery/templates/migration/user_activation.rb +9 -0
  23. data/lib/sorcery.rb +85 -0
  24. data/lib/sorcery/adapters/active_record_adapter.rb +120 -0
  25. data/lib/sorcery/adapters/base_adapter.rb +30 -0
  26. data/lib/sorcery/controller.rb +157 -0
  27. data/lib/sorcery/controller/config.rb +65 -0
  28. data/lib/sorcery/controller/submodules/activity_logging.rb +82 -0
  29. data/lib/sorcery/controller/submodules/brute_force_protection.rb +38 -0
  30. data/lib/sorcery/controller/submodules/external.rb +199 -0
  31. data/lib/sorcery/controller/submodules/http_basic_auth.rb +74 -0
  32. data/lib/sorcery/controller/submodules/remember_me.rb +81 -0
  33. data/lib/sorcery/controller/submodules/session_timeout.rb +56 -0
  34. data/lib/sorcery/crypto_providers/aes256.rb +51 -0
  35. data/lib/sorcery/crypto_providers/bcrypt.rb +97 -0
  36. data/lib/sorcery/crypto_providers/common.rb +35 -0
  37. data/lib/sorcery/crypto_providers/md5.rb +19 -0
  38. data/lib/sorcery/crypto_providers/sha1.rb +28 -0
  39. data/lib/sorcery/crypto_providers/sha256.rb +36 -0
  40. data/lib/sorcery/crypto_providers/sha512.rb +36 -0
  41. data/lib/sorcery/engine.rb +21 -0
  42. data/lib/sorcery/model.rb +183 -0
  43. data/lib/sorcery/model/config.rb +96 -0
  44. data/lib/sorcery/model/submodules/activity_logging.rb +70 -0
  45. data/lib/sorcery/model/submodules/brute_force_protection.rb +125 -0
  46. data/lib/sorcery/model/submodules/external.rb +100 -0
  47. data/lib/sorcery/model/submodules/remember_me.rb +62 -0
  48. data/lib/sorcery/model/submodules/reset_password.rb +131 -0
  49. data/lib/sorcery/model/submodules/user_activation.rb +149 -0
  50. data/lib/sorcery/model/temporary_token.rb +30 -0
  51. data/lib/sorcery/protocols/certs/ca-bundle.crt +5182 -0
  52. data/lib/sorcery/protocols/oauth.rb +42 -0
  53. data/lib/sorcery/protocols/oauth2.rb +47 -0
  54. data/lib/sorcery/providers/base.rb +27 -0
  55. data/lib/sorcery/providers/facebook.rb +63 -0
  56. data/lib/sorcery/providers/github.rb +51 -0
  57. data/lib/sorcery/providers/google.rb +51 -0
  58. data/lib/sorcery/providers/jira.rb +77 -0
  59. data/lib/sorcery/providers/linkedin.rb +66 -0
  60. data/lib/sorcery/providers/liveid.rb +53 -0
  61. data/lib/sorcery/providers/twitter.rb +59 -0
  62. data/lib/sorcery/providers/vk.rb +63 -0
  63. data/lib/sorcery/providers/xing.rb +64 -0
  64. data/lib/sorcery/railties/tasks.rake +6 -0
  65. data/lib/sorcery/test_helpers/internal.rb +78 -0
  66. data/lib/sorcery/test_helpers/internal/rails.rb +68 -0
  67. data/lib/sorcery/test_helpers/rails/controller.rb +21 -0
  68. data/lib/sorcery/test_helpers/rails/integration.rb +26 -0
  69. data/lib/sorcery/version.rb +3 -0
  70. data/sorcery.gemspec +34 -0
  71. data/spec/active_record/user_activation_spec.rb +18 -0
  72. data/spec/active_record/user_activity_logging_spec.rb +17 -0
  73. data/spec/active_record/user_brute_force_protection_spec.rb +16 -0
  74. data/spec/active_record/user_oauth_spec.rb +16 -0
  75. data/spec/active_record/user_remember_me_spec.rb +16 -0
  76. data/spec/active_record/user_reset_password_spec.rb +16 -0
  77. data/spec/active_record/user_spec.rb +37 -0
  78. data/spec/controllers/controller_activity_logging_spec.rb +124 -0
  79. data/spec/controllers/controller_brute_force_protection_spec.rb +43 -0
  80. data/spec/controllers/controller_http_basic_auth_spec.rb +68 -0
  81. data/spec/controllers/controller_oauth2_spec.rb +407 -0
  82. data/spec/controllers/controller_oauth_spec.rb +240 -0
  83. data/spec/controllers/controller_remember_me_spec.rb +117 -0
  84. data/spec/controllers/controller_session_timeout_spec.rb +80 -0
  85. data/spec/controllers/controller_spec.rb +215 -0
  86. data/spec/orm/active_record.rb +21 -0
  87. data/spec/rails_app/app/active_record/authentication.rb +3 -0
  88. data/spec/rails_app/app/active_record/user.rb +5 -0
  89. data/spec/rails_app/app/active_record/user_provider.rb +3 -0
  90. data/spec/rails_app/app/controllers/sorcery_controller.rb +265 -0
  91. data/spec/rails_app/app/helpers/application_helper.rb +2 -0
  92. data/spec/rails_app/app/mailers/sorcery_mailer.rb +32 -0
  93. data/spec/rails_app/app/views/application/index.html.erb +17 -0
  94. data/spec/rails_app/app/views/layouts/application.html.erb +14 -0
  95. data/spec/rails_app/app/views/sorcery_mailer/activation_email.html.erb +17 -0
  96. data/spec/rails_app/app/views/sorcery_mailer/activation_email.text.erb +9 -0
  97. data/spec/rails_app/app/views/sorcery_mailer/activation_needed_email.html.erb +17 -0
  98. data/spec/rails_app/app/views/sorcery_mailer/activation_success_email.html.erb +17 -0
  99. data/spec/rails_app/app/views/sorcery_mailer/activation_success_email.text.erb +9 -0
  100. data/spec/rails_app/app/views/sorcery_mailer/reset_password_email.html.erb +16 -0
  101. data/spec/rails_app/app/views/sorcery_mailer/reset_password_email.text.erb +8 -0
  102. data/spec/rails_app/app/views/sorcery_mailer/send_unlock_token_email.text.erb +1 -0
  103. data/spec/rails_app/config.ru +4 -0
  104. data/spec/rails_app/config/application.rb +56 -0
  105. data/spec/rails_app/config/boot.rb +4 -0
  106. data/spec/rails_app/config/database.yml +22 -0
  107. data/spec/rails_app/config/environment.rb +5 -0
  108. data/spec/rails_app/config/environments/test.rb +37 -0
  109. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  110. data/spec/rails_app/config/initializers/inflections.rb +10 -0
  111. data/spec/rails_app/config/initializers/mime_types.rb +5 -0
  112. data/spec/rails_app/config/initializers/secret_token.rb +7 -0
  113. data/spec/rails_app/config/initializers/session_store.rb +12 -0
  114. data/spec/rails_app/config/locales/en.yml +5 -0
  115. data/spec/rails_app/config/routes.rb +48 -0
  116. data/spec/rails_app/db/migrate/activation/20101224223622_add_activation_to_users.rb +17 -0
  117. data/spec/rails_app/db/migrate/activity_logging/20101224223624_add_activity_logging_to_users.rb +19 -0
  118. data/spec/rails_app/db/migrate/brute_force_protection/20101224223626_add_brute_force_protection_to_users.rb +13 -0
  119. data/spec/rails_app/db/migrate/core/20101224223620_create_users.rb +16 -0
  120. data/spec/rails_app/db/migrate/external/20101224223628_create_authentications_and_user_providers.rb +22 -0
  121. data/spec/rails_app/db/migrate/remember_me/20101224223623_add_remember_me_token_to_users.rb +15 -0
  122. data/spec/rails_app/db/migrate/reset_password/20101224223622_add_reset_password_to_users.rb +13 -0
  123. data/spec/rails_app/db/schema.rb +23 -0
  124. data/spec/rails_app/db/seeds.rb +7 -0
  125. data/spec/shared_examples/user_activation_shared_examples.rb +242 -0
  126. data/spec/shared_examples/user_activity_logging_shared_examples.rb +97 -0
  127. data/spec/shared_examples/user_brute_force_protection_shared_examples.rb +156 -0
  128. data/spec/shared_examples/user_oauth_shared_examples.rb +36 -0
  129. data/spec/shared_examples/user_remember_me_shared_examples.rb +57 -0
  130. data/spec/shared_examples/user_reset_password_shared_examples.rb +263 -0
  131. data/spec/shared_examples/user_shared_examples.rb +467 -0
  132. data/spec/sorcery_crypto_providers_spec.rb +198 -0
  133. data/spec/spec.opts +2 -0
  134. data/spec/spec_helper.rb +41 -0
  135. metadata +350 -0
@@ -0,0 +1,97 @@
1
+ shared_examples_for "rails_3_activity_logging_model" do
2
+ context "loaded plugin configuration" do
3
+ before(:all) do
4
+ sorcery_reload!([:activity_logging])
5
+ end
6
+
7
+ after(:each) do
8
+ User.sorcery_config.reset!
9
+ end
10
+
11
+ it "allows configuration option 'last_login_at_attribute_name'" do
12
+ sorcery_model_property_set(:last_login_at_attribute_name, :login_time)
13
+
14
+ expect(User.sorcery_config.last_login_at_attribute_name).to eq :login_time
15
+ end
16
+
17
+ it "allows configuration option 'last_logout_at_attribute_name'" do
18
+ sorcery_model_property_set(:last_logout_at_attribute_name, :logout_time)
19
+ expect(User.sorcery_config.last_logout_at_attribute_name).to eq :logout_time
20
+ end
21
+
22
+ it "allows configuration option 'last_activity_at_attribute_name'" do
23
+ sorcery_model_property_set(:last_activity_at_attribute_name, :activity_time)
24
+ expect(User.sorcery_config.last_activity_at_attribute_name).to eq :activity_time
25
+ end
26
+
27
+ it "allows configuration option 'last_login_from_ip_adress'" do
28
+ sorcery_model_property_set(:last_login_from_ip_address_name, :ip_address)
29
+ expect(User.sorcery_config.last_login_from_ip_address_name).to eq :ip_address
30
+ end
31
+
32
+ describe ".current_users" do
33
+ let(:user) { create_new_user }
34
+
35
+ it "is empty when no users are logged in" do
36
+ expect(User.current_users).to be_empty
37
+ end
38
+
39
+ it "holds the user object when 1 user is logged in" do
40
+ user.set_last_activity_at(Time.now.in_time_zone)
41
+
42
+ expect(User.current_users).to match([User.sorcery_adapter.find(user.id)])
43
+ end
44
+
45
+ it "'current_users' shows all current_users, whether they have logged out before or not." do
46
+ User.sorcery_adapter.delete_all
47
+ user1 = create_new_user({:username => 'gizmo1', :email => "bla1@bla.com", :password => 'secret1'})
48
+ user2 = create_new_user({:username => 'gizmo2', :email => "bla2@bla.com", :password => 'secret2'})
49
+ user3 = create_new_user({:username => 'gizmo3', :email => "bla3@bla.com", :password => 'secret3'})
50
+
51
+ now = Time.now.in_time_zone
52
+ [user1, user2, user3].each do |user|
53
+ user.set_last_login_at(now)
54
+ user.set_last_activity_at(now)
55
+ end
56
+
57
+ expect(User.current_users.map(&:id)).to match_array([user1, user2, user3].map(&:id))
58
+ Timecop.travel now + 5
59
+ user1.set_last_logout_at(Time.now.in_time_zone)
60
+ expect(User.current_users.map(&:id)).to match_array([user2, user3].map(&:id))
61
+ Timecop.return
62
+ end
63
+
64
+ end
65
+
66
+ it '.set_last_login_at update last_login_at' do
67
+ user = create_new_user
68
+ now = Time.now.in_time_zone
69
+ expect(user.sorcery_adapter).to receive(:update_attribute).with(:last_login_at, now)
70
+
71
+ user.set_last_login_at(now)
72
+ end
73
+
74
+ it '.set_last_logout_at update last_logout_at' do
75
+ user = create_new_user
76
+ now = Time.now.in_time_zone
77
+ expect(user.sorcery_adapter).to receive(:update_attribute).with(:last_logout_at, now)
78
+
79
+ user.set_last_logout_at(now)
80
+ end
81
+
82
+ it '.set_last_activity_at update last_activity_at' do
83
+ user = create_new_user
84
+ now = Time.now.in_time_zone
85
+ expect(user.sorcery_adapter).to receive(:update_attribute).with(:last_activity_at, now)
86
+
87
+ user.set_last_activity_at(now)
88
+ end
89
+
90
+ it '.set_last_ip_addess update last_login_from_ip_address' do
91
+ user = create_new_user
92
+ expect(user.sorcery_adapter).to receive(:update_attribute).with(:last_login_from_ip_address, '0.0.0.0')
93
+
94
+ user.set_last_ip_addess('0.0.0.0')
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,156 @@
1
+ shared_examples_for "rails_3_brute_force_protection_model" do
2
+ let(:user) { create_new_user }
3
+ before(:each) do
4
+ User.sorcery_adapter.delete_all
5
+ end
6
+
7
+
8
+ context "loaded plugin configuration" do
9
+
10
+ let(:config) { User.sorcery_config }
11
+
12
+ before(:all) do
13
+ sorcery_reload!([:brute_force_protection])
14
+ end
15
+
16
+ after(:each) do
17
+ User.sorcery_config.reset!
18
+ end
19
+
20
+ specify { expect(user).to respond_to(:failed_logins_count) }
21
+ specify { expect(user).to respond_to(:lock_expires_at) }
22
+
23
+ it "enables configuration option 'failed_logins_count_attribute_name'" do
24
+ sorcery_model_property_set(:failed_logins_count_attribute_name, :my_count)
25
+ expect(config.failed_logins_count_attribute_name).to eq :my_count
26
+ end
27
+
28
+ it "enables configuration option 'lock_expires_at_attribute_name'" do
29
+ sorcery_model_property_set(:lock_expires_at_attribute_name, :expires)
30
+ expect(config.lock_expires_at_attribute_name).to eq :expires
31
+ end
32
+
33
+ it "enables configuration option 'consecutive_login_retries_amount_allowed'" do
34
+ sorcery_model_property_set(:consecutive_login_retries_amount_limit, 34)
35
+ expect(config.consecutive_login_retries_amount_limit).to eq 34
36
+ end
37
+
38
+ it "enables configuration option 'login_lock_time_period'" do
39
+ sorcery_model_property_set(:login_lock_time_period, 2.hours)
40
+ expect(config.login_lock_time_period).to eq 2.hours
41
+ end
42
+
43
+ describe "#locked?" do
44
+ it "is locked" do
45
+ user.send("#{config.lock_expires_at_attribute_name}=", Time.now + 5.days)
46
+ expect(user).to be_locked
47
+ end
48
+
49
+ it "isn't locked" do
50
+ user.send("#{config.lock_expires_at_attribute_name}=", nil)
51
+ expect(user).not_to be_locked
52
+ end
53
+ end
54
+ end
55
+
56
+ describe "#register_failed_login!" do
57
+ it "locks user when number of retries reached the limit" do
58
+ expect(user.lock_expires_at).to be_nil
59
+
60
+ sorcery_model_property_set(:consecutive_login_retries_amount_limit, 1)
61
+ user.register_failed_login!
62
+ lock_expires_at = User.sorcery_adapter.find_by_id(user.id).lock_expires_at
63
+
64
+ expect(lock_expires_at).not_to be_nil
65
+ end
66
+
67
+ context "unlock_token_mailer_disabled is true" do
68
+ it "does not automatically send unlock email" do
69
+ sorcery_model_property_set(:unlock_token_mailer_disabled, true)
70
+ sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
71
+ sorcery_model_property_set(:login_lock_time_period, 0)
72
+ sorcery_model_property_set(:unlock_token_mailer, SorceryMailer)
73
+
74
+ 3.times { user.register_failed_login! }
75
+
76
+ expect(ActionMailer::Base.deliveries.size).to eq 0
77
+
78
+ end
79
+ end
80
+
81
+ context "unlock_token_mailer_disabled is false" do
82
+ before do
83
+ sorcery_model_property_set(:unlock_token_mailer_disabled, false)
84
+ sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
85
+ sorcery_model_property_set(:login_lock_time_period, 0)
86
+ sorcery_model_property_set(:unlock_token_mailer, SorceryMailer)
87
+ end
88
+
89
+ it "does not automatically send unlock email" do
90
+ 3.times { user.register_failed_login! }
91
+
92
+ expect(ActionMailer::Base.deliveries.size).to eq 1
93
+ end
94
+
95
+ it "generates unlock token before mail is sent" do
96
+ 3.times { user.register_failed_login! }
97
+
98
+ expect(ActionMailer::Base.deliveries.last.body.to_s.match(user.unlock_token)).not_to be_nil
99
+ end
100
+ end
101
+ end
102
+
103
+ context ".authenticate" do
104
+
105
+ it "unlocks after lock time period passes" do
106
+ sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
107
+ sorcery_model_property_set(:login_lock_time_period, 0.2)
108
+ 2.times { user.register_failed_login! }
109
+
110
+ lock_expires_at = User.sorcery_adapter.find_by_id(user.id).lock_expires_at
111
+ expect(lock_expires_at).not_to be_nil
112
+
113
+ Timecop.travel(Time.now.in_time_zone + 0.3)
114
+ User.authenticate('bla@bla.com', 'secret')
115
+
116
+ lock_expires_at = User.sorcery_adapter.find_by_id(user.id).lock_expires_at
117
+ expect(lock_expires_at).to be_nil
118
+ Timecop.return
119
+ end
120
+
121
+ it "doest not unlock if time period is 0 (permanent lock)" do
122
+ sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
123
+ sorcery_model_property_set(:login_lock_time_period, 0)
124
+
125
+ 2.times { user.register_failed_login! }
126
+
127
+ unlock_date = user.lock_expires_at
128
+ Timecop.travel(Time.now.in_time_zone + 1)
129
+
130
+ user.register_failed_login!
131
+
132
+ expect(user.lock_expires_at.to_s).to eq unlock_date.to_s
133
+ Timecop.return
134
+ end
135
+
136
+ end
137
+
138
+ describe "#unlock!" do
139
+ it "unlocks after entering unlock token" do
140
+ sorcery_model_property_set(:consecutive_login_retries_amount_limit, 2)
141
+ sorcery_model_property_set(:login_lock_time_period, 0)
142
+ sorcery_model_property_set(:unlock_token_mailer, SorceryMailer)
143
+ 3.times { user.register_failed_login! }
144
+
145
+ expect(user.unlock_token).not_to be_nil
146
+
147
+ token = user.unlock_token
148
+ user = User.load_from_unlock_token(token)
149
+
150
+ expect(user).not_to be_nil
151
+
152
+ user.unlock!
153
+ expect(User.load_from_unlock_token(user.unlock_token)).to be_nil
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,36 @@
1
+ shared_examples_for "rails_3_oauth_model" do
2
+ # ----------------- PLUGIN CONFIGURATION -----------------------
3
+
4
+ let(:external_user) { create_new_external_user :twitter }
5
+
6
+ describe "loaded plugin configuration" do
7
+
8
+ before(:all) do
9
+ Authentication.sorcery_adapter.delete_all
10
+ User.sorcery_adapter.delete_all
11
+
12
+ sorcery_reload!([:external])
13
+ sorcery_controller_property_set(:external_providers, [:twitter])
14
+ sorcery_model_property_set(:authentications_class, Authentication)
15
+ sorcery_controller_external_property_set(:twitter, :key, "eYVNBjBDi33aa9GkA3w")
16
+ sorcery_controller_external_property_set(:twitter, :secret, "XpbeSdCoaKSmQGSeokz5qcUATClRW5u08QWNfv71N8")
17
+ sorcery_controller_external_property_set(:twitter, :callback_url, "http://blabla.com")
18
+ end
19
+
20
+ it "responds to 'load_from_provider'" do
21
+ expect(User).to respond_to(:load_from_provider)
22
+ end
23
+
24
+ it "'load_from_provider' loads user if exists" do
25
+ external_user
26
+ expect(User.load_from_provider :twitter, 123).to eq external_user
27
+ end
28
+
29
+ it "'load_from_provider' returns nil if user doesn't exist" do
30
+ external_user
31
+ expect(User.load_from_provider :twitter, 980342).to be_nil
32
+ end
33
+
34
+ end
35
+
36
+ end
@@ -0,0 +1,57 @@
1
+ shared_examples_for "rails_3_remember_me_model" do
2
+ let(:user) { create_new_user }
3
+
4
+ describe "loaded plugin configuration" do
5
+
6
+ before(:all) do
7
+ sorcery_reload!([:remember_me])
8
+ end
9
+
10
+ after(:each) do
11
+ User.sorcery_config.reset!
12
+ end
13
+
14
+ it "allows configuration option 'remember_me_token_attribute_name'" do
15
+ sorcery_model_property_set(:remember_me_token_attribute_name, :my_token)
16
+
17
+ expect(User.sorcery_config.remember_me_token_attribute_name).to eq :my_token
18
+ end
19
+
20
+ it "allows configuration option 'remember_me_token_expires_at_attribute_name'" do
21
+ sorcery_model_property_set(:remember_me_token_expires_at_attribute_name, :my_expires)
22
+
23
+ expect(User.sorcery_config.remember_me_token_expires_at_attribute_name).to eq :my_expires
24
+ end
25
+
26
+ specify { expect(user).to respond_to :remember_me! }
27
+
28
+ specify { expect(user).to respond_to :forget_me! }
29
+
30
+ it "generates a new token on 'remember_me!'" do
31
+ expect(user.remember_me_token).to be_nil
32
+
33
+ user.remember_me!
34
+
35
+ expect(user.remember_me_token).not_to be_nil
36
+ end
37
+
38
+ # FIXME: assert on line 37 sometimes fails by a second
39
+ it "sets an expiration based on 'remember_me_for' attribute" do
40
+ sorcery_model_property_set(:remember_me_for, 2 * 60 * 60 * 24)
41
+ user.remember_me!
42
+
43
+ expect(user.remember_me_token_expires_at.utc.to_s).to eq (Time.now.in_time_zone + 2 * 60 * 60 * 24).utc.to_s
44
+ end
45
+
46
+ it "deletes the token and expiration on 'forget_me!'" do
47
+ user.remember_me!
48
+
49
+ expect(user.remember_me_token).not_to be_nil
50
+
51
+ user.forget_me!
52
+
53
+ expect(user.remember_me_token).to be_nil
54
+ expect(user.remember_me_token_expires_at).to be_nil
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,263 @@
1
+ shared_examples_for "rails_3_reset_password_model" do
2
+ # ----------------- PLUGIN CONFIGURATION -----------------------
3
+ let(:user) { create_new_user }
4
+
5
+ describe "loaded plugin configuration" do
6
+
7
+ before(:all) do
8
+ sorcery_reload!([:reset_password], :reset_password_mailer => ::SorceryMailer)
9
+ end
10
+
11
+ after(:each) do
12
+ User.sorcery_config.reset!
13
+ end
14
+
15
+ context "API" do
16
+
17
+ specify { expect(user).to respond_to :deliver_reset_password_instructions! }
18
+
19
+ specify { expect(user).to respond_to :change_password! }
20
+
21
+ it "responds to .load_from_reset_password_token" do
22
+ expect(User).to respond_to :load_from_reset_password_token
23
+ end
24
+ end
25
+
26
+ it "allows configuration option 'reset_password_token_attribute_name'" do
27
+ sorcery_model_property_set(:reset_password_token_attribute_name, :my_code)
28
+
29
+ expect(User.sorcery_config.reset_password_token_attribute_name).to eq :my_code
30
+ end
31
+
32
+ it "allows configuration option 'reset_password_mailer'" do
33
+ sorcery_model_property_set(:reset_password_mailer, TestUser)
34
+
35
+ expect(User.sorcery_config.reset_password_mailer).to eq TestUser
36
+ end
37
+
38
+ it "enables configuration option 'reset_password_mailer_disabled'" do
39
+ sorcery_model_property_set(:reset_password_mailer_disabled, :my_reset_password_mailer_disabled)
40
+
41
+ expect(User.sorcery_config.reset_password_mailer_disabled).to eq :my_reset_password_mailer_disabled
42
+ end
43
+
44
+ it "if mailer is nil and mailer is enabled, throw exception!" do
45
+ expect{sorcery_reload!([:reset_password], :reset_password_mailer_disabled => false)}.to raise_error(ArgumentError)
46
+ end
47
+
48
+ it "if mailer is disabled and mailer is nil, do NOT throw exception" do
49
+ expect{sorcery_reload!([:reset_password], :reset_password_mailer_disabled => true)}.to_not raise_error
50
+ end
51
+
52
+ it "allows configuration option 'reset_password_email_method_name'" do
53
+ sorcery_model_property_set(:reset_password_email_method_name, :my_mailer_method)
54
+
55
+ expect(User.sorcery_config.reset_password_email_method_name).to eq :my_mailer_method
56
+ end
57
+
58
+ it "allows configuration option 'reset_password_expiration_period'" do
59
+ sorcery_model_property_set(:reset_password_expiration_period, 16)
60
+
61
+ expect(User.sorcery_config.reset_password_expiration_period).to eq 16
62
+ end
63
+
64
+ it "allows configuration option 'reset_password_email_sent_at_attribute_name'" do
65
+ sorcery_model_property_set(:reset_password_email_sent_at_attribute_name, :blabla)
66
+
67
+ expect(User.sorcery_config.reset_password_email_sent_at_attribute_name).to eq :blabla
68
+ end
69
+
70
+ it "allows configuration option 'reset_password_time_between_emails'" do
71
+ sorcery_model_property_set(:reset_password_time_between_emails, 16)
72
+
73
+ expect(User.sorcery_config.reset_password_time_between_emails).to eq 16
74
+ end
75
+ end
76
+
77
+
78
+ describe "when activated with sorcery" do
79
+
80
+ before(:all) do
81
+ sorcery_reload!([:reset_password], :reset_password_mailer => ::SorceryMailer)
82
+ end
83
+
84
+ before(:each) do
85
+ User.sorcery_adapter.delete_all
86
+ user
87
+ end
88
+
89
+ after(:each) do
90
+ Timecop.return
91
+ end
92
+
93
+ it "load_from_reset_password_token returns user when token is found" do
94
+ user.generate_reset_password_token!
95
+ updated_user = User.sorcery_adapter.find(user.id)
96
+
97
+ expect(User.load_from_reset_password_token user.reset_password_token).to eq updated_user
98
+ end
99
+
100
+ it "load_from_reset_password_token does NOT return user when token is NOT found" do
101
+ user.generate_reset_password_token!
102
+
103
+ expect(User.load_from_reset_password_token "a").to be_nil
104
+ end
105
+
106
+ it "load_from_reset_password_token returns user when token is found and not expired" do
107
+ sorcery_model_property_set(:reset_password_expiration_period, 500)
108
+ user.generate_reset_password_token!
109
+ updated_user = User.sorcery_adapter.find(user.id)
110
+
111
+ expect(User.load_from_reset_password_token user.reset_password_token).to eq updated_user
112
+ end
113
+
114
+ it "load_from_reset_password_token does NOT return user when token is found and expired" do
115
+ sorcery_model_property_set(:reset_password_expiration_period, 0.1)
116
+ user.generate_reset_password_token!
117
+ Timecop.travel(Time.now.in_time_zone+0.5)
118
+
119
+ expect(User.load_from_reset_password_token user.reset_password_token).to be_nil
120
+ end
121
+
122
+ it "load_from_reset_password_token is always valid if expiration period is nil" do
123
+ sorcery_model_property_set(:reset_password_expiration_period, nil)
124
+ user.generate_reset_password_token!
125
+ updated_user = User.sorcery_adapter.find(user.id)
126
+
127
+ expect(User.load_from_reset_password_token user.reset_password_token).to eq updated_user
128
+ end
129
+
130
+ it "load_from_reset_password_token returns nil if token is blank" do
131
+ expect(User.load_from_reset_password_token nil).to be_nil
132
+ expect(User.load_from_reset_password_token "").to be_nil
133
+ end
134
+
135
+ it "'deliver_reset_password_instructions!' generates a reset_password_token" do
136
+ expect(user.reset_password_token).to be_nil
137
+
138
+ user.deliver_reset_password_instructions!
139
+
140
+ expect(user.reset_password_token).not_to be_nil
141
+ end
142
+
143
+ it "the reset_password_token is random" do
144
+ sorcery_model_property_set(:reset_password_time_between_emails, 0)
145
+ user.deliver_reset_password_instructions!
146
+ old_password_code = user.reset_password_token
147
+ user.deliver_reset_password_instructions!
148
+
149
+ expect(user.reset_password_token).not_to eq old_password_code
150
+ end
151
+
152
+ context "mailer is enabled" do
153
+ it "sends an email on reset" do
154
+ old_size = ActionMailer::Base.deliveries.size
155
+ user.deliver_reset_password_instructions!
156
+
157
+ expect(ActionMailer::Base.deliveries.size).to eq old_size + 1
158
+ end
159
+
160
+ it "calls send_reset_password_email! on reset" do
161
+ expect(user).to receive(:send_reset_password_email!).once
162
+
163
+ user.deliver_reset_password_instructions!
164
+ end
165
+
166
+ it "does not send an email if time between emails has not passed since last email" do
167
+ sorcery_model_property_set(:reset_password_time_between_emails, 10000)
168
+ old_size = ActionMailer::Base.deliveries.size
169
+ user.deliver_reset_password_instructions!
170
+
171
+ expect(ActionMailer::Base.deliveries.size).to eq old_size + 1
172
+
173
+ user.deliver_reset_password_instructions!
174
+
175
+ expect(ActionMailer::Base.deliveries.size).to eq old_size + 1
176
+ end
177
+
178
+ it "sends an email if time between emails has passed since last email" do
179
+ sorcery_model_property_set(:reset_password_time_between_emails, 0.5)
180
+ old_size = ActionMailer::Base.deliveries.size
181
+ user.deliver_reset_password_instructions!
182
+
183
+ expect(ActionMailer::Base.deliveries.size).to eq old_size + 1
184
+
185
+ Timecop.travel(Time.now.in_time_zone+0.5)
186
+ user.deliver_reset_password_instructions!
187
+
188
+ expect(ActionMailer::Base.deliveries.size).to eq old_size + 2
189
+ end
190
+ end
191
+
192
+ context "mailer is disabled" do
193
+
194
+ before(:all) do
195
+ sorcery_reload!([:reset_password], :reset_password_mailer_disabled => true, :reset_password_mailer => ::SorceryMailer)
196
+ end
197
+
198
+ it "sends an email on reset" do
199
+ old_size = ActionMailer::Base.deliveries.size
200
+ user.deliver_reset_password_instructions!
201
+
202
+ expect(ActionMailer::Base.deliveries.size).to eq old_size
203
+ end
204
+
205
+ it "does not call send_reset_password_email! on reset" do
206
+ expect(user).to receive(:send_reset_password_email!).never
207
+
208
+ user.deliver_reset_password_instructions!
209
+ end
210
+
211
+ it "does not send an email if time between emails has not passed since last email" do
212
+ sorcery_model_property_set(:reset_password_time_between_emails, 10000)
213
+ old_size = ActionMailer::Base.deliveries.size
214
+ user.deliver_reset_password_instructions!
215
+
216
+ expect(ActionMailer::Base.deliveries.size).to eq old_size
217
+
218
+ user.deliver_reset_password_instructions!
219
+
220
+ expect(ActionMailer::Base.deliveries.size).to eq old_size
221
+ end
222
+
223
+ it "sends an email if time between emails has passed since last email" do
224
+ sorcery_model_property_set(:reset_password_time_between_emails, 0.5)
225
+ old_size = ActionMailer::Base.deliveries.size
226
+ user.deliver_reset_password_instructions!
227
+
228
+ expect(ActionMailer::Base.deliveries.size).to eq old_size
229
+
230
+ Timecop.travel(Time.now.in_time_zone+0.5)
231
+ user.deliver_reset_password_instructions!
232
+
233
+ expect(ActionMailer::Base.deliveries.size).to eq old_size
234
+ end
235
+ end
236
+
237
+ it "when change_password! is called, deletes reset_password_token" do
238
+ user.deliver_reset_password_instructions!
239
+
240
+ expect(user.reset_password_token).not_to be_nil
241
+
242
+ user.change_password!("blabulsdf")
243
+ user.save!
244
+
245
+ expect(user.reset_password_token).to be_nil
246
+ end
247
+
248
+ it "returns false if time between emails has not passed since last email" do
249
+ sorcery_model_property_set(:reset_password_time_between_emails, 10000)
250
+ user.deliver_reset_password_instructions!
251
+
252
+ expect(user.deliver_reset_password_instructions!).to be false
253
+ end
254
+
255
+ it "encrypts properly on reset" do
256
+ user.deliver_reset_password_instructions!
257
+ user.change_password!("blagu")
258
+
259
+ expect(Sorcery::CryptoProviders::BCrypt.matches? user.crypted_password, "blagu", user.salt).to be true
260
+ end
261
+
262
+ end
263
+ end