door_mat 0.0.5

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 (176) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +3 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.md +88 -0
  6. data/Rakefile +32 -0
  7. data/app/assets/javascripts/door_mat/application.js +13 -0
  8. data/app/assets/stylesheets/door_mat/application.css +15 -0
  9. data/app/assets/stylesheets/scaffold.css +56 -0
  10. data/app/controllers/door_mat/activities_controller.rb +106 -0
  11. data/app/controllers/door_mat/application_controller.rb +14 -0
  12. data/app/controllers/door_mat/change_password_controller.rb +32 -0
  13. data/app/controllers/door_mat/forgot_passwords_controller.rb +57 -0
  14. data/app/controllers/door_mat/manage_email_controller.rb +61 -0
  15. data/app/controllers/door_mat/password_less_session_controller.rb +121 -0
  16. data/app/controllers/door_mat/reconfirm_password_controller.rb +27 -0
  17. data/app/controllers/door_mat/sessions_controller.rb +17 -0
  18. data/app/controllers/door_mat/sign_in_controller.rb +60 -0
  19. data/app/controllers/door_mat/sign_up_controller.rb +59 -0
  20. data/app/controllers/door_mat/static_controller.rb +5 -0
  21. data/app/mailers/door_mat/activity_mailer.rb +18 -0
  22. data/app/mailers/door_mat/password_less_session_mailer.rb +12 -0
  23. data/app/models/door_mat/access_token.rb +315 -0
  24. data/app/models/door_mat/activity.rb +14 -0
  25. data/app/models/door_mat/activity_confirm_email.rb +45 -0
  26. data/app/models/door_mat/activity_download_recovery_key.rb +30 -0
  27. data/app/models/door_mat/activity_reset_password.rb +47 -0
  28. data/app/models/door_mat/actor.rb +149 -0
  29. data/app/models/door_mat/change_password.rb +12 -0
  30. data/app/models/door_mat/email.rb +58 -0
  31. data/app/models/door_mat/forgot_password.rb +12 -0
  32. data/app/models/door_mat/membership.rb +42 -0
  33. data/app/models/door_mat/session.rb +315 -0
  34. data/app/models/door_mat/sign_in.rb +31 -0
  35. data/app/models/door_mat/sign_up.rb +17 -0
  36. data/app/views/door_mat/activity_mailer/confirm_email.html.erb +11 -0
  37. data/app/views/door_mat/activity_mailer/confirm_email.text.erb +7 -0
  38. data/app/views/door_mat/activity_mailer/reset_password.html.erb +11 -0
  39. data/app/views/door_mat/activity_mailer/reset_password.text.erb +7 -0
  40. data/app/views/door_mat/change_password/new.html.erb +22 -0
  41. data/app/views/door_mat/forgot_passwords/choose_new_password.html.erb +34 -0
  42. data/app/views/door_mat/forgot_passwords/new.html.erb +14 -0
  43. data/app/views/door_mat/helpers/_errors_if_any.html.erb +10 -0
  44. data/app/views/door_mat/manage_email/new.html.erb +14 -0
  45. data/app/views/door_mat/password_less_session/access_token.html.erb +16 -0
  46. data/app/views/door_mat/password_less_session/new.html.erb +34 -0
  47. data/app/views/door_mat/password_less_session_mailer/send_token.html.erb +11 -0
  48. data/app/views/door_mat/password_less_session_mailer/send_token.text.erb +7 -0
  49. data/app/views/door_mat/reconfirm_password/new.html.erb +12 -0
  50. data/app/views/door_mat/sign_in/new.html.erb +30 -0
  51. data/app/views/door_mat/sign_up/new.html.erb +24 -0
  52. data/app/views/door_mat/static/add_email_success.html.erb +5 -0
  53. data/app/views/door_mat/static/change_password_success.html.erb +2 -0
  54. data/app/views/door_mat/static/confirm_email_success.html.erb +2 -0
  55. data/app/views/door_mat/static/email_confirmation_required.html.erb +17 -0
  56. data/app/views/door_mat/static/forgot_password_verification_mail_sent.html.erb +2 -0
  57. data/app/views/door_mat/static/reconfirm_password_success.html.erb +4 -0
  58. data/app/views/door_mat/static/sign_in_success.html.erb +5 -0
  59. data/app/views/door_mat/static/sign_out_success.html.erb +5 -0
  60. data/app/views/door_mat/static/sign_up_success.html.erb +4 -0
  61. data/bin/rails +12 -0
  62. data/config/locales/en.yml +73 -0
  63. data/config/routes.rb +48 -0
  64. data/db/migrate/20140616234935_create_door_mat_actors.rb +23 -0
  65. data/db/migrate/20140617233357_create_door_mat_sessions.rb +17 -0
  66. data/db/migrate/20140630043202_create_door_mat_emails.rb +12 -0
  67. data/db/migrate/20140702045729_create_door_mat_activities.rb +14 -0
  68. data/db/migrate/20141115183045_create_door_mat_access_tokens.rb +17 -0
  69. data/db/migrate/20141121191824_create_door_mat_memberships.rb +14 -0
  70. data/db/migrate/20150910182126_rename_session_guid_column.rb +5 -0
  71. data/db/migrate/20150918210831_add_access_token_rating_column.rb +5 -0
  72. data/door_mat.gemspec +37 -0
  73. data/lib/door_mat.rb +20 -0
  74. data/lib/door_mat/attr_asymmetric_store.rb +82 -0
  75. data/lib/door_mat/attr_symmetric_store.rb +82 -0
  76. data/lib/door_mat/configuration.rb +193 -0
  77. data/lib/door_mat/controller.rb +117 -0
  78. data/lib/door_mat/crypto.rb +49 -0
  79. data/lib/door_mat/crypto/asymmetric_store.rb +77 -0
  80. data/lib/door_mat/crypto/fast_hash.rb +17 -0
  81. data/lib/door_mat/crypto/password_hash.rb +39 -0
  82. data/lib/door_mat/crypto/secure_compare.rb +23 -0
  83. data/lib/door_mat/crypto/symmetric_store.rb +68 -0
  84. data/lib/door_mat/engine.rb +23 -0
  85. data/lib/door_mat/process/actor_password_change.rb +65 -0
  86. data/lib/door_mat/process/actor_sign_in.rb +38 -0
  87. data/lib/door_mat/process/actor_sign_up.rb +39 -0
  88. data/lib/door_mat/process/create_new_anonymous_actor.rb +36 -0
  89. data/lib/door_mat/process/manage_email.rb +42 -0
  90. data/lib/door_mat/process/reset_password.rb +50 -0
  91. data/lib/door_mat/regex.rb +17 -0
  92. data/lib/door_mat/test_helper.rb +58 -0
  93. data/lib/door_mat/url_protocol.rb +9 -0
  94. data/lib/door_mat/version.rb +3 -0
  95. data/lib/tasks/door_mat_tasks.rake +31 -0
  96. data/spec/controllers/door_mat/activities_controller_spec.rb +70 -0
  97. data/spec/controllers/door_mat/forgot_passwords_controller_spec.rb +57 -0
  98. data/spec/controllers/door_mat/manage_email_spec.rb +181 -0
  99. data/spec/controllers/door_mat/password_less_session_controller_spec.rb +344 -0
  100. data/spec/controllers/door_mat/sign_in_controller_spec.rb +211 -0
  101. data/spec/controllers/door_mat/sign_up_controller_spec.rb +90 -0
  102. data/spec/factories/door_mat_access_tokens.rb +6 -0
  103. data/spec/factories/door_mat_activitiess.rb +6 -0
  104. data/spec/factories/door_mat_actors.rb +23 -0
  105. data/spec/factories/door_mat_emails.rb +14 -0
  106. data/spec/factories/door_mat_memberships.rb +6 -0
  107. data/spec/factories/door_mat_sessions.rb +24 -0
  108. data/spec/features/password_less_session_spec.rb +165 -0
  109. data/spec/features/remember_me_spec.rb +672 -0
  110. data/spec/features/session_spec.rb +336 -0
  111. data/spec/lib/attr_store_spec.rb +237 -0
  112. data/spec/lib/crypto_spec.rb +130 -0
  113. data/spec/lib/process_spec.rb +159 -0
  114. data/spec/models/door_mat/access_token_spec.rb +134 -0
  115. data/spec/models/door_mat/activity_spec.rb +38 -0
  116. data/spec/models/door_mat/actor_spec.rb +56 -0
  117. data/spec/models/door_mat/email_spec.rb +25 -0
  118. data/spec/models/door_mat/session_spec.rb +69 -0
  119. data/spec/spec_helper.rb +223 -0
  120. data/spec/support/timecop/timecop_helper.rb +52 -0
  121. data/spec/test_app/README.rdoc +28 -0
  122. data/spec/test_app/Rakefile +6 -0
  123. data/spec/test_app/app/assets/javascripts/application.js +13 -0
  124. data/spec/test_app/app/assets/stylesheets/application.css +15 -0
  125. data/spec/test_app/app/controllers/account_controller.rb +28 -0
  126. data/spec/test_app/app/controllers/application_controller.rb +10 -0
  127. data/spec/test_app/app/controllers/password_less_sample_controller.rb +56 -0
  128. data/spec/test_app/app/controllers/static_controller.rb +7 -0
  129. data/spec/test_app/app/helpers/account_helper.rb +2 -0
  130. data/spec/test_app/app/helpers/application_helper.rb +2 -0
  131. data/spec/test_app/app/models/game.rb +62 -0
  132. data/spec/test_app/app/models/shared_data.rb +4 -0
  133. data/spec/test_app/app/models/shared_key.rb +8 -0
  134. data/spec/test_app/app/models/user_detail.rb +7 -0
  135. data/spec/test_app/app/views/account/show.html.erb +133 -0
  136. data/spec/test_app/app/views/door_mat/static/sign_out_success.html.erb +7 -0
  137. data/spec/test_app/app/views/layouts/application.html.erb +20 -0
  138. data/spec/test_app/app/views/password_less_sample/draw_results.html.erb +6 -0
  139. data/spec/test_app/app/views/password_less_sample/final_result.html.erb +7 -0
  140. data/spec/test_app/app/views/password_less_sample/play_game.html.erb +5 -0
  141. data/spec/test_app/app/views/password_less_sample/show_loosing_door.html.erb +10 -0
  142. data/spec/test_app/app/views/static/index.html.erb +12 -0
  143. data/spec/test_app/app/views/static/only_confirmed_email_allowed.html.erb +10 -0
  144. data/spec/test_app/app/views/static/page_that_require_password_reconfirmation.html.erb +16 -0
  145. data/spec/test_app/app/views/static/session_protected_page.html.erb +32 -0
  146. data/spec/test_app/bin/bundle +3 -0
  147. data/spec/test_app/bin/rails +4 -0
  148. data/spec/test_app/bin/rake +4 -0
  149. data/spec/test_app/config.ru +4 -0
  150. data/spec/test_app/config/application.rb +29 -0
  151. data/spec/test_app/config/boot.rb +5 -0
  152. data/spec/test_app/config/database.yml +25 -0
  153. data/spec/test_app/config/environment.rb +19 -0
  154. data/spec/test_app/config/environments/development.rb +50 -0
  155. data/spec/test_app/config/environments/production.rb +83 -0
  156. data/spec/test_app/config/environments/test.rb +48 -0
  157. data/spec/test_app/config/initializers/backtrace_silencers.rb +7 -0
  158. data/spec/test_app/config/initializers/cookies_serializer.rb +3 -0
  159. data/spec/test_app/config/initializers/door_mat.rb +72 -0
  160. data/spec/test_app/config/initializers/filter_parameter_logging.rb +4 -0
  161. data/spec/test_app/config/initializers/inflections.rb +16 -0
  162. data/spec/test_app/config/initializers/mime_types.rb +4 -0
  163. data/spec/test_app/config/initializers/session_store.rb +3 -0
  164. data/spec/test_app/config/initializers/wrap_parameters.rb +14 -0
  165. data/spec/test_app/config/locales/en.yml +23 -0
  166. data/spec/test_app/config/routes.rb +42 -0
  167. data/spec/test_app/config/secrets.yml +31 -0
  168. data/spec/test_app/db/migrate/20140717182813_create_user_details.rb +10 -0
  169. data/spec/test_app/db/migrate/20140908225256_create_shared_data.rb +10 -0
  170. data/spec/test_app/db/migrate/20140908225604_create_shared_keys.rb +11 -0
  171. data/spec/test_app/db/migrate/20141121190714_create_games.rb +10 -0
  172. data/spec/test_app/public/404.html +67 -0
  173. data/spec/test_app/public/422.html +67 -0
  174. data/spec/test_app/public/500.html +66 -0
  175. data/spec/test_app/public/favicon.ico +0 -0
  176. metadata +552 -0
@@ -0,0 +1,38 @@
1
+ module DoorMat
2
+ module Process
3
+ class ActorSignIn
4
+
5
+ def self.with(email, password, is_public, remember_me, request, cookies)
6
+ # Destroy any session linked to existing cookies before
7
+ # replacing it by a new session
8
+ DoorMat::Session.destroy_if_linked_to(cookies)
9
+
10
+ actor = DoorMat::Actor.authenticate_with(email, password)
11
+ return false if actor.blank?
12
+
13
+ DoorMat::Session.for(actor, password, request)
14
+ return false unless DoorMat::Session.current_session.valid?
15
+
16
+ if is_public
17
+ DoorMat::Session.current_session.public_computer!
18
+ else
19
+ DoorMat::Session.current_session.private_computer!
20
+ end
21
+
22
+ # User requested to be remembered
23
+ if DoorMat.configuration.allow_remember_me_feature && remember_me
24
+ DoorMat::Session.current_session.remember_me! unless (
25
+ DoorMat.configuration.remember_me_require_private_computer_confirmation &&
26
+ DoorMat::Session.current_session.public_computer?
27
+ )
28
+ end
29
+
30
+ actor.sessions << DoorMat::Session.current_session
31
+ DoorMat::Session.current_session.set_up(cookies)
32
+ true
33
+ end
34
+
35
+ end
36
+ end
37
+ end
38
+
@@ -0,0 +1,39 @@
1
+ module DoorMat
2
+ module Process
3
+ class ActorSignUp
4
+
5
+ def self.with(address, password, request, cookies, controller)
6
+ # Destroy any session linked to existing cookies before
7
+ # replacing it by a new session
8
+ DoorMat::Session.destroy_if_linked_to(cookies)
9
+
10
+ # Sign up with the credentials of
11
+ # an existing account fails
12
+ return false if DoorMat::Actor.authenticate_with(address, password)
13
+
14
+ actor = DoorMat::Actor.create_with(password)
15
+ return false if actor.blank?
16
+
17
+ email = DoorMat::Email.for(address)
18
+ email.status = :not_available if DoorMat::Email.count_matching(address) >= DoorMat::configuration.plausible_deniability_count
19
+ actor.current_email = email
20
+ DoorMat::Session.for(actor, password, request)
21
+ return false unless DoorMat::Session.current_session.valid?
22
+
23
+ actor.sessions << DoorMat::Session.current_session
24
+ actor.emails << email
25
+
26
+ # setup public key pairs
27
+ actor.setup_public_key_pairs(DoorMat::Session.current_session)
28
+
29
+ return false unless actor.save
30
+
31
+ DoorMat::Session.current_session.set_up(cookies)
32
+ DoorMat::ActivityConfirmEmail.for(email, controller)
33
+ DoorMat::ActivityDownloadRecoveryKey.for(actor)
34
+ true
35
+ end
36
+
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,36 @@
1
+ module DoorMat
2
+ module Process
3
+ class CreateNewAnonymousActor
4
+
5
+ def self.owned_by(owner)
6
+ password = DoorMat::Crypto::SymmetricStore.random_key
7
+ anonymous_actor = Actor.create_with(password)
8
+ return nil if anonymous_actor.blank?
9
+
10
+ sub_session = DoorMat::Session.new_sub_session_for_actor(anonymous_actor, password)
11
+ anonymous_actor.setup_public_key_pairs(sub_session)
12
+
13
+ owner.with_lock do
14
+ anonymous_actor.save!
15
+
16
+ if DoorMat::Session.current_session.append_sub_session(sub_session)
17
+ membership = DoorMat::Membership.new
18
+ membership.member = owner
19
+ membership.member_of = anonymous_actor
20
+ membership.sponsor = DoorMat::Membership.sponsors[:sponsor_true]
21
+ membership.owner = DoorMat::Membership.owners[:owner_true]
22
+ membership.permission = DoorMat::Membership.permissions[:no_permission]
23
+ membership.key = password
24
+ membership.save!
25
+ end
26
+ end
27
+
28
+ anonymous_actor
29
+ rescue Exception => e
30
+ DoorMat.configuration.logger.error "ERROR: CreateNewAnonymousActor failed to with error - #{e}"
31
+ nil
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,42 @@
1
+ module DoorMat
2
+ module Process
3
+ class ManageEmail
4
+
5
+ def self.add(email, actor, controller)
6
+ return false unless email.valid?
7
+
8
+ actor.with_lock do
9
+ return false unless actor.can_add_email? email
10
+
11
+ email.status = :not_available if DoorMat::Email.count_matching(email.address) > DoorMat::configuration.plausible_deniability_count
12
+
13
+ actor.emails << email
14
+
15
+ DoorMat::ActivityConfirmEmail.for(email, controller)
16
+ end
17
+
18
+ true
19
+ end
20
+
21
+ def self.set_primary(encoded_address, actor)
22
+ actor.with_lock do
23
+ email = actor.email_from_urlsafe_encoded(encoded_address)
24
+ return false if email.blank?
25
+
26
+ return true if email.primary?
27
+
28
+ return false unless email.confirmed?
29
+
30
+ actor.emails.primary.each do |e|
31
+ e.confirmed!
32
+ end
33
+
34
+ email.primary!
35
+ end
36
+
37
+ true
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,50 @@
1
+ module DoorMat
2
+ module Process
3
+ class ResetPassword
4
+
5
+ def self.for(address, controller)
6
+ emails = DoorMat::Email.confirmed_matching(address)
7
+ return false if emails.blank?
8
+
9
+ # Several DoorMat::Email could match the address
10
+ # pick the first one for now.
11
+ # They will all be tested at reset time to apply the reset to the proper one
12
+ email = emails.first
13
+
14
+ # Because email was loaded without a valid session
15
+ # the address attribute is still encrypted.
16
+ # Temporarily update it here with the plain text.
17
+ # The reason it is trusted is because the hash
18
+ # of the user input matched a previously confirmed email address
19
+ # hash already in the system.
20
+ email.address = address
21
+
22
+ DoorMat::ActivityResetPassword.for(email, controller)
23
+ true
24
+ end
25
+
26
+ def self.with(forgot_password)
27
+ emails = DoorMat::Email.confirmed_matching(forgot_password.email)
28
+ return false if emails.blank?
29
+
30
+ activity = DoorMat::ActivityResetPassword.with(forgot_password.token, emails)
31
+ return false if activity.blank?
32
+
33
+ return false if forgot_password.recovery_key.blank?
34
+ recovery_key = forgot_password.recovery_key.read
35
+
36
+ emails.each do |email|
37
+ if DoorMat::Process::ActorPasswordChange.after_password_reset(email.actor, forgot_password.password, recovery_key)
38
+ DoorMat::ActivityDownloadRecoveryKey.for(email.actor)
39
+ activity.done!
40
+ return true
41
+ end
42
+ end
43
+
44
+ activity.failed!
45
+ return false
46
+ end
47
+
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,17 @@
1
+ module DoorMat
2
+ module Regex
3
+
4
+ def self.simple_email
5
+ # http://tools.ietf.org/html/rfc3696#section-3
6
+ # min 1 char local part and min 2 char domain part
7
+ # max 64 char local part and max 255 char domain part
8
+ # first and last char can not be blank
9
+ /\A\S.{0,63}@.{1,254}\S\z/
10
+ end
11
+
12
+ def self.session_guid
13
+ /\A[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\z/
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,58 @@
1
+ module DoorMat
2
+ module TestHelper
3
+
4
+ def self.create_signed_up_actor_with_confirmed_email_address(address="me@example.com", password="n7f3d;3#)")
5
+ actor, _ = create_signed_in_actor_with_confirmed_email_address(address, password)
6
+ DoorMat::Session.clear_current_session
7
+ actor
8
+ end
9
+
10
+ def self.create_signed_in_actor_with_confirmed_email_address(address="me@example.com", password="n7f3d;3#)")
11
+ DoorMat::Session.clear_current_session
12
+ actor = DoorMat::Actor.create_with(password)
13
+
14
+ email = DoorMat::Email.for(address)
15
+ email.status = :primary
16
+
17
+ session = DoorMat::Session.new
18
+ session.ip = "request.remote_ip"
19
+ session.agent = "request.user_agent"
20
+ actor.current_email = email
21
+
22
+ RequestStore.store[:current_session] = session.initialize_with(actor, password)
23
+
24
+ actor.sessions << DoorMat::Session.current_session
25
+ actor.emails << email
26
+
27
+ # setup public key pairs
28
+ actor.setup_public_key_pairs(DoorMat::Session.current_session)
29
+
30
+ actor.save!
31
+
32
+ DoorMat::ActivityDownloadRecoveryKey.for(actor)
33
+ [actor, RequestStore.store[:current_session]]
34
+ end
35
+
36
+ def self.sign_in_existing_actor(address="me@example.com", password="n7f3d;3#)")
37
+ DoorMat::Session.clear_current_session
38
+ actor = DoorMat::Actor.authenticate_with(address, password)
39
+
40
+ session = DoorMat::Session.new
41
+ session.ip = "request.remote_ip"
42
+ session.agent = "request.user_agent"
43
+
44
+ RequestStore.store[:current_session] = session.initialize_with(actor, password)
45
+
46
+ actor.sessions << DoorMat::Session.current_session
47
+ actor.save!
48
+
49
+ [actor, RequestStore.store[:current_session]]
50
+ end
51
+
52
+ def self.sign_out(session)
53
+ session.destroy! if session.persisted?
54
+ RequestStore.store[:current_session] = nil
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,9 @@
1
+ module DoorMat
2
+ module UrlProtocol
3
+
4
+ def self.url_protocol
5
+ Rails.application.config.force_ssl ? 'https' : 'http'
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module DoorMat
2
+ VERSION = "0.0.5"
3
+ end
@@ -0,0 +1,31 @@
1
+ require 'door_mat'
2
+ require 'door_mat/test_helper'
3
+
4
+ namespace :door_mat do
5
+
6
+ desc "Create an admin actor in the system, useful if you need to share data between a user and the system - specify admin_account_email and admin_account_pwd in your rails secret file using environment variables."
7
+ task :create_admin_actor => :environment do
8
+
9
+ if DoorMat::Email.matching(Rails.application.secrets.admin_account_email).count == 0
10
+ DoorMat::TestHelper.create_signed_up_actor_with_confirmed_email_address(
11
+ Rails.application.secrets.admin_account_email,
12
+ Rails.application.secrets.admin_account_pwd
13
+ )
14
+ puts "SUCCESS: #{Rails.application.secrets.admin_account_email} is now defined in the database"
15
+ else
16
+ puts "ERROR: #{Rails.application.secrets.admin_account_email} is already defined in the database"
17
+ end
18
+
19
+ end
20
+
21
+ desc "Environment cleanup before building gem"
22
+ task :cleanup => :environment do
23
+ list = Dir['spec/test_app/db/*sqlite3', 'spec/test_app/db/schema.rb', 'spec/test_app/tmp', 'spec/test_app/log/*log']
24
+ list.each do |file|
25
+ FileUtils.remove_entry_secure(file)
26
+ puts file
27
+ end
28
+ puts "Ready to run: rake build"
29
+ end
30
+
31
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ module DoorMat
4
+ describe ActivitiesController do
5
+ routes { DoorMat::Engine.routes }
6
+ let(:user) { {email: 'user@example.com', password: 'k#dkvKfdj38g!'} }
7
+
8
+ describe '#resend_email_confirmation' do
9
+ it 'redirects to :back if the email is invalid' do
10
+ _, _ = TestHelper::create_signed_in_actor_with_confirmed_email_address(user[:email], user[:password])
11
+ @request.headers["HTTP_REFERER"] = '/some_path'
12
+ post :resend_email_confirmation, {email: 'invalid_email'}
13
+ expect(response).to have_http_status(302)
14
+ expect(response).to redirect_to('/some_path')
15
+ end
16
+
17
+ it 'redirects to :confirm_email_success if the email is already confirmed' do
18
+ actor, _ = TestHelper::create_signed_in_actor_with_confirmed_email_address(user[:email], user[:password])
19
+ @request.headers["HTTP_REFERER"] = '/some_path'
20
+ post :resend_email_confirmation, {email: actor.current_email.to_urlsafe_encoded}
21
+ expect(response).to have_http_status(302)
22
+ expect(response).to redirect_to('/confirm_email_success')
23
+ end
24
+
25
+ it 'redirects to :back if the address is not confirmed' do
26
+ actor, _ = TestHelper::create_signed_in_actor_with_confirmed_email_address(user[:email], user[:password])
27
+ email = DoorMat::Email.for('new_address@example.com')
28
+ actor.emails << email
29
+
30
+ @request.headers["HTTP_REFERER"] = '/some_path'
31
+ post :resend_email_confirmation, {email: email.to_urlsafe_encoded}
32
+ expect(response).to have_http_status(302)
33
+ expect(response).to redirect_to('/some_path')
34
+ end
35
+
36
+
37
+ it 'redirects to main app root url if the address is not confirmed and HTTP_REFERER is not set' do
38
+ actor, _ = TestHelper::create_signed_in_actor_with_confirmed_email_address(user[:email], user[:password])
39
+ email = DoorMat::Email.for('new_address@example.com')
40
+ actor.emails << email
41
+
42
+ post :resend_email_confirmation, {email: email.to_urlsafe_encoded}
43
+ expect(response).to have_http_status(302)
44
+ expect(response).to redirect_to('/')
45
+ end
46
+
47
+ end
48
+
49
+ describe '#confirm_email' do
50
+ it 'redirects to :back after an invalid email confirmation request' do
51
+ _, _ = TestHelper::create_signed_in_actor_with_confirmed_email_address(user[:email], user[:password])
52
+ @request.headers["HTTP_REFERER"] = '/some_path'
53
+ get :confirm_email, {token: 'invalid_token', email: 'invalid_email'}
54
+ expect(response).to have_http_status(302)
55
+ expect(response).to redirect_to('/some_path')
56
+ end
57
+ end
58
+
59
+ describe '#download_recovery_key' do
60
+ it 'redirects to :back after an invalid download request' do
61
+ _, _ = TestHelper::create_signed_in_actor_with_confirmed_email_address(user[:email], user[:password])
62
+ @request.headers["HTTP_REFERER"] = '/some_path'
63
+ post :download_recovery_key
64
+ expect(response).to have_http_status(302)
65
+ expect(response).to redirect_to('/some_path')
66
+ end
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ module DoorMat
4
+ describe ForgotPasswordsController do
5
+ routes { DoorMat::Engine.routes }
6
+ let(:user) { {email: 'user@example.com', password: 'k#dkvKfdj38g!'} }
7
+
8
+ describe '#create' do
9
+ render_views
10
+
11
+ it 'render new if the user input validation fails' do
12
+ post :create, forgot_password: {email: 'email'}
13
+ expect(response).to have_http_status(200)
14
+ expect(response.body).to match(/Email is invalid/)
15
+ end
16
+
17
+ it 'redirects the user to the same page no matter if the email exists or not in the system' do
18
+ _ = TestHelper::create_signed_up_actor_with_confirmed_email_address(user[:email], user[:password])
19
+
20
+ post :create, {"utf8"=>"✓", "forgot_password"=>{"email"=>user[:email]} }
21
+ expect(response).to have_http_status(302)
22
+ expect(response).to redirect_to('/forgot_password_verification_mail_sent')
23
+
24
+ post :create, {"utf8"=>"✓", "forgot_password"=>{"email"=>"not_an_actual_user@example.com"} }
25
+ expect(response).to have_http_status(302)
26
+ expect(response).to redirect_to('/forgot_password_verification_mail_sent')
27
+ end
28
+
29
+ end
30
+
31
+ describe '#reset_password' do
32
+ render_views
33
+
34
+ it 'render choose_new_password if something is wrong with the user inputs' do
35
+ post :reset_password, forgot_password: {email: 'email'}
36
+ expect(response).to have_http_status(200)
37
+ expect(response.body).to match(/Password is too short/)
38
+ end
39
+
40
+ it 'redirects the user to the sign in url if the password reset is successful' do
41
+ allow(DoorMat::Process::ResetPassword).to receive(:with).and_return(true)
42
+ post :reset_password, forgot_password: {email: user[:email], password: user[:password], password_confirmation: user[:password]}
43
+ expect(response).to have_http_status(302)
44
+ expect(response).to redirect_to('/sign_in')
45
+ end
46
+
47
+ it 'redirect the user to the start of the forgot password recovery process if an error occurs' do
48
+ allow(DoorMat::Process::ResetPassword).to receive(:with).and_return(false)
49
+ post :reset_password, forgot_password: {email: user[:email], password: user[:password], password_confirmation: user[:password]}
50
+ expect(response).to have_http_status(302)
51
+ expect(response).to redirect_to('/forgot_password')
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+ end