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,181 @@
1
+ require 'spec_helper'
2
+
3
+ module DoorMat
4
+ describe ManageEmailController 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 'redirects back after successfully adding a new email' do
12
+ _, _ = TestHelper::create_signed_in_actor_with_confirmed_email_address(user[:email], user[:password])
13
+ DoorMat.configuration.add_email_success_url = [ :request, :referer ]
14
+
15
+ @request.headers["HTTP_REFERER"] = '/some_path'
16
+ allow(DoorMat::ActivityConfirmEmail).to receive(:for)
17
+ get :create, email: {address: 'other_user@example.com'}
18
+ expect(flash[:notice]).to match(/New email address successfully added/)
19
+ expect(response).to have_http_status(302)
20
+ expect(response).to redirect_to('/some_path')
21
+ DoorMat.configuration.add_email_success_url = [:main_app, :account_show_url]
22
+ end
23
+
24
+ it 'renders new if the submitted email is not valid' do
25
+ _, _ = TestHelper::create_signed_in_actor_with_confirmed_email_address(user[:email], user[:password])
26
+ @request.headers["HTTP_REFERER"] = '/some_path'
27
+ get :create, email: {address: 'invalid_email'}
28
+ expect(response.body).to match(/Address is invalid/)
29
+ expect(response).to have_http_status(200)
30
+ end
31
+
32
+ end
33
+
34
+ describe '#destroy' do
35
+
36
+ it 'can delete the non primary email attached to an actor' do
37
+ actor, session = TestHelper::create_signed_in_actor_with_confirmed_email_address(user[:email], user[:password])
38
+ email = actor.emails.first
39
+ email.confirmed!
40
+
41
+ other_email = DoorMat::Email.for('other_user@example.com')
42
+ controller = Object.new
43
+ allow(DoorMat::ActivityConfirmEmail).to receive(:for)
44
+ DoorMat::Process::ManageEmail.add(other_email, actor, controller)
45
+ other_email = actor.emails.last
46
+ other_email.primary!
47
+
48
+ TestHelper::sign_out(session)
49
+ actor, _ = TestHelper::sign_in_existing_actor('other_user@example.com', user[:password])
50
+
51
+ @request.headers["HTTP_REFERER"] = '/some_path'
52
+ expect(actor.emails.count).to eq 2
53
+ get :destroy, {email: email.to_urlsafe_encoded}
54
+ expect(actor.emails.count).to eq 1
55
+ expect(flash[:notice]).to match(/Email deleted/)
56
+ expect(response).to have_http_status(302)
57
+ expect(response).to redirect_to('/some_path')
58
+ end
59
+
60
+ it 'can not delete the email used to sign in to the current session' do
61
+ actor, _ = TestHelper::create_signed_in_actor_with_confirmed_email_address(user[:email], user[:password])
62
+ email = actor.emails.first
63
+ email.confirmed!
64
+
65
+ other_email = DoorMat::Email.for('other_user@example.com')
66
+ controller = Object.new
67
+ allow(DoorMat::ActivityConfirmEmail).to receive(:for)
68
+ DoorMat::Process::ManageEmail.add(other_email, actor, controller)
69
+ other_email = actor.emails.last
70
+ other_email.primary!
71
+
72
+ @request.headers["HTTP_REFERER"] = '/some_path'
73
+ expect(actor.emails.count).to eq 2
74
+ get :destroy, {email: email.to_urlsafe_encoded}
75
+ expect(actor.emails.count).to eq 2
76
+ expect(flash[:alert]).to match(/Can not delete the email address you are currently logged in with/)
77
+ expect(response).to have_http_status(302)
78
+ expect(response).to redirect_to('/some_path')
79
+ end
80
+
81
+ it 'can not delete the only email attached to an actor' do
82
+ actor, _ = TestHelper::create_signed_in_actor_with_confirmed_email_address(user[:email], user[:password])
83
+ email = actor.emails.first
84
+ @request.headers["HTTP_REFERER"] = '/some_path'
85
+ expect(actor.emails.count).to eq 1
86
+ get :destroy, {email: email.to_urlsafe_encoded}
87
+ expect(actor.emails.count).to eq 1
88
+ expect(flash[:alert]).to match(/Can not delete the only email address associated with this account/)
89
+ expect(response).to have_http_status(302)
90
+ expect(response).to redirect_to('/some_path')
91
+ end
92
+
93
+ it 'can not delete the primary email attached to an actor' do
94
+ actor, _ = TestHelper::create_signed_in_actor_with_confirmed_email_address(user[:email], user[:password])
95
+
96
+ other_email = DoorMat::Email.for('other_user@example.com')
97
+ controller = Object.new
98
+ allow(DoorMat::ActivityConfirmEmail).to receive(:for)
99
+ DoorMat::Process::ManageEmail.add(other_email, actor, controller)
100
+ other_email.primary!
101
+
102
+ @request.headers["HTTP_REFERER"] = '/some_path'
103
+ expect(actor.emails.count).to eq 2
104
+ get :destroy, {email: other_email.to_urlsafe_encoded}
105
+ expect(actor.emails.count).to eq 2
106
+ expect(flash[:alert]).to match(/Primary email can not be deleted/)
107
+ expect(response).to have_http_status(302)
108
+ expect(response).to redirect_to('/some_path')
109
+ end
110
+
111
+ it 'can not delete an email attached to a different actor' do
112
+ actor = TestHelper::create_signed_up_actor_with_confirmed_email_address('other_user@example.com')
113
+ email = actor.emails.first
114
+ _, _ = TestHelper::create_signed_in_actor_with_confirmed_email_address(user[:email], user[:password])
115
+ @request.headers["HTTP_REFERER"] = '/some_path'
116
+ expect(actor.emails.count).to eq 1
117
+ expect(DoorMat::Email.all.count).to eq 2
118
+ get :destroy, {email: email.to_urlsafe_encoded}
119
+ expect(actor.emails.count).to eq 1
120
+ expect(DoorMat::Email.all.count).to eq 2
121
+ expect(flash[:alert]).to match(/The specified email can not be deleted/)
122
+ expect(response).to have_http_status(302)
123
+ expect(response).to redirect_to('/some_path')
124
+ end
125
+
126
+ it 'can not delete an email that is not in the system' do
127
+ actor, _ = TestHelper::create_signed_in_actor_with_confirmed_email_address(user[:email], user[:password])
128
+ email = DoorMat::Email.for('other_user@example.com')
129
+ @request.headers["HTTP_REFERER"] = '/some_path'
130
+ expect(actor.emails.count).to eq 1
131
+ get :destroy, {email: email.to_urlsafe_encoded}
132
+ expect(actor.emails.count).to eq 1
133
+ expect(flash[:alert]).to match(/The specified email can not be deleted/)
134
+ expect(response).to have_http_status(302)
135
+ expect(response).to redirect_to('/some_path')
136
+ end
137
+
138
+ end
139
+
140
+ describe '#set_primary_email' do
141
+
142
+ it 'succeed at setting the primary email' do
143
+ actor, _ = TestHelper::create_signed_in_actor_with_confirmed_email_address(user[:email], user[:password])
144
+ email = actor.emails.first
145
+ email.confirmed!
146
+
147
+ other_email = DoorMat::Email.for('other_user@example.com')
148
+ controller = Object.new
149
+ allow(DoorMat::ActivityConfirmEmail).to receive(:for)
150
+ DoorMat::Process::ManageEmail.add(other_email, actor, controller)
151
+ other_email = actor.emails.last
152
+ other_email.primary!
153
+
154
+ @request.headers["HTTP_REFERER"] = '/some_path'
155
+ post :set_primary_email, {email: email.to_urlsafe_encoded}
156
+ expect(flash[:notice]).to match(/Primary email was set/)
157
+ expect(response).to have_http_status(302)
158
+ expect(response).to redirect_to('/some_path')
159
+ end
160
+
161
+ it 'fails at setting the primary email if the email is not confirmed' do
162
+ actor, _ = TestHelper::create_signed_in_actor_with_confirmed_email_address(user[:email], user[:password])
163
+
164
+ other_email = DoorMat::Email.for('other_user@example.com')
165
+ controller = Object.new
166
+ allow(DoorMat::ActivityConfirmEmail).to receive(:for)
167
+ DoorMat::Process::ManageEmail.add(other_email, actor, controller)
168
+ other_email = actor.emails.last
169
+ other_email.not_confirmed!
170
+
171
+ @request.headers["HTTP_REFERER"] = '/some_path'
172
+ post :set_primary_email, {email: other_email.to_urlsafe_encoded}
173
+ expect(flash[:alert]).to match(/Primary email could not be set/)
174
+ expect(response).to have_http_status(302)
175
+ expect(response).to redirect_to('/some_path')
176
+ end
177
+
178
+ end
179
+
180
+ end
181
+ end
@@ -0,0 +1,344 @@
1
+ require 'spec_helper'
2
+
3
+ module DoorMat
4
+ describe PasswordLessSessionController do
5
+ include EmailSpec::Helpers
6
+ include EmailSpec::Matchers
7
+
8
+ describe '#create' do
9
+ render_views
10
+
11
+ def accept_valid_token_get_request(via_post = true)
12
+ admin = {email: Rails.application.secrets.admin_account_email, password: Rails.application.secrets.admin_account_pwd}
13
+ DoorMat::TestHelper.create_signed_up_actor_with_confirmed_email_address(admin[:email], admin[:password])
14
+
15
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"user1@example.com"}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
16
+ expect(response).to have_http_status(302)
17
+ expect(response).to redirect_to('/access_token/big_ticket')
18
+ expect(DoorMat::AccessToken.first.single_use?).to be true
19
+
20
+ e = open_last_email_for("user1@example.com")
21
+ link_in_email = links_in_email(e).select {|url| /access_token/.match(url)}.first
22
+ token = test_only_session_guid_anywhere_regex.match(link_in_email)[0]
23
+ if via_post
24
+ post :access_token_post, access_token: {token_for: :big_ticket, identifier: token}, use_route: :door_mat
25
+ else
26
+ get :access_token, token_for: :big_ticket, token: token, use_route: :door_mat
27
+ end
28
+
29
+ expect(response).to have_http_status(302)
30
+ expect(response).to redirect_to('/draw_results')
31
+ expect(DoorMat::AccessToken.first.used?).to be true
32
+ end
33
+
34
+ it 'accepts a valid access token request via post' do
35
+ accept_valid_token_get_request(via_post = true)
36
+ end
37
+
38
+ it 'accepts a valid access token request via get' do
39
+ accept_valid_token_get_request(via_post = false)
40
+ end
41
+
42
+ def reject_token_request_that_fail_address_validation(via_post = true, validation_method = :reject_cheaters)
43
+ admin = {email: Rails.application.secrets.admin_account_email, password: Rails.application.secrets.admin_account_pwd}
44
+ DoorMat::TestHelper.create_signed_up_actor_with_confirmed_email_address(admin[:email], admin[:password])
45
+
46
+ case validation_method
47
+ when :reject_cheaters
48
+ user_address = 'cheat@cheater.com'
49
+ DoorMat.configuration.password_less_sessions[:big_ticket][:validate] = -> (address) { /@cheater.com\z/.match(address).blank? } # Don't let those cheaters play the game...
50
+ when :existing_members_only
51
+ user_address = 'bob@example.com'
52
+ DoorMat.configuration.password_less_sessions[:big_ticket][:validate] = -> (address) { DoorMat::Email.count_matching(address) > 0 } # Must be a registered user to play the game...
53
+ end
54
+
55
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>user_address, "confirm_identifier"=>user_address}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
56
+ expect(response).to have_http_status(302)
57
+ expect(response).to redirect_to('/access_token/big_ticket')
58
+ expect(DoorMat::AccessToken.first.single_use?).to be true
59
+
60
+ e = open_last_email_for(user_address)
61
+ link_in_email = links_in_email(e).select {|url| /access_token/.match(url)}.first
62
+ token = test_only_session_guid_anywhere_regex.match(link_in_email)[0]
63
+ if via_post
64
+ post :access_token_post, access_token: {token_for: :big_ticket, identifier: token}, use_route: :door_mat
65
+ else
66
+ get :access_token, token_for: :big_ticket, token: token, use_route: :door_mat
67
+ end
68
+
69
+ expect(response).to have_http_status(200)
70
+ expect(response.body).to match(/Something looks wrong with your access token/)
71
+ expect(DoorMat::AccessToken.count).to eq(0)
72
+
73
+ DoorMat.configuration.password_less_sessions[:big_ticket][:validate] = false
74
+ end
75
+
76
+ it 'reject token requests that fail address validation via post' do
77
+ reject_token_request_that_fail_address_validation(via_post = true, validation_method = :reject_cheaters)
78
+ reject_token_request_that_fail_address_validation(via_post = true, validation_method = :existing_members_only)
79
+ end
80
+
81
+ it 'reject token requests that fail address validation via get' do
82
+ reject_token_request_that_fail_address_validation(via_post = false, validation_method = :reject_cheaters)
83
+ reject_token_request_that_fail_address_validation(via_post = false, validation_method = :existing_members_only)
84
+ end
85
+
86
+ def accept_token_request_that_succeed_address_validation(via_post = true, validation_method = :reject_cheaters)
87
+ admin = {email: Rails.application.secrets.admin_account_email, password: Rails.application.secrets.admin_account_pwd}
88
+ DoorMat::TestHelper.create_signed_up_actor_with_confirmed_email_address(admin[:email], admin[:password])
89
+
90
+ user_address = 'bob@example.com'
91
+ case validation_method
92
+ when :reject_cheaters
93
+ DoorMat.configuration.password_less_sessions[:big_ticket][:validate] = -> (address) { /@cheater.com\z/.match(address).blank? } # Don't let those cheaters play the game...
94
+ when :existing_members_only
95
+ DoorMat::TestHelper.create_signed_up_actor_with_confirmed_email_address(user_address, 'user_password')
96
+ DoorMat.configuration.password_less_sessions[:big_ticket][:validate] = -> (address) { DoorMat::Email.count_matching(address) > 0 } # Must be a registered user to play the game...
97
+ end
98
+
99
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>user_address, "confirm_identifier"=>user_address}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
100
+ expect(response).to have_http_status(302)
101
+ expect(response).to redirect_to('/access_token/big_ticket')
102
+ expect(DoorMat::AccessToken.first.single_use?).to be true
103
+
104
+ e = open_last_email_for(user_address)
105
+ link_in_email = links_in_email(e).select {|url| /access_token/.match(url)}.first
106
+ token = test_only_session_guid_anywhere_regex.match(link_in_email)[0]
107
+ if via_post
108
+ post :access_token_post, access_token: {token_for: :big_ticket, identifier: token}, use_route: :door_mat
109
+ else
110
+ get :access_token, token_for: :big_ticket, token: token, use_route: :door_mat
111
+ end
112
+
113
+ expect(response).to have_http_status(302)
114
+ expect(response).to redirect_to('/draw_results')
115
+ expect(DoorMat::AccessToken.first.used?).to be true
116
+
117
+ DoorMat.configuration.password_less_sessions[:big_ticket][:validate] = false
118
+ end
119
+
120
+ it 'accept token requests that succeed address validation via post 1' do
121
+ accept_token_request_that_succeed_address_validation(via_post = true, validation_method = :reject_cheaters)
122
+ end
123
+
124
+ it 'accept token requests that succeed address validation via post 2' do
125
+ accept_token_request_that_succeed_address_validation(via_post = true, validation_method = :existing_members_only)
126
+ end
127
+
128
+ it 'accept token requests that succeed address validation via get 1' do
129
+ accept_token_request_that_succeed_address_validation(via_post = false, validation_method = :reject_cheaters)
130
+ end
131
+
132
+ it 'accept token requests that succeed address validation via get 1' do
133
+ accept_token_request_that_succeed_address_validation(via_post = false, validation_method = :existing_members_only)
134
+ end
135
+
136
+ def reject_malformed_late_inexistent_token_request(via_post = true)
137
+ admin = {email: Rails.application.secrets.admin_account_email, password: Rails.application.secrets.admin_account_pwd}
138
+ DoorMat::TestHelper.create_signed_up_actor_with_confirmed_email_address(admin[:email], admin[:password])
139
+
140
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"user1@example.com"}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
141
+ expect(response).to have_http_status(302)
142
+ expect(response).to redirect_to('/access_token/big_ticket')
143
+ expect(DoorMat::AccessToken.first.single_use?).to be true
144
+
145
+ e = open_last_email_for("user1@example.com")
146
+ link_in_email = links_in_email(e).select {|url| /access_token/.match(url)}.first
147
+ token = test_only_session_guid_anywhere_regex.match(link_in_email)[0]
148
+
149
+ if via_post
150
+ post :access_token_post, access_token: {token_for: :big_ticket, identifier: token[0..-2]}, use_route: :door_mat
151
+ else
152
+ get :access_token, token_for: :big_ticket, token: token[0..-2], use_route: :door_mat
153
+ end
154
+
155
+ expect(response).to have_http_status(200)
156
+ expect(response.body).to match(/format of your access token is invalid/)
157
+ expect(DoorMat::AccessToken.first.used?).to be false
158
+
159
+ wait_two_days
160
+
161
+ if via_post
162
+ post :access_token_post, access_token: {token_for: :big_ticket, identifier: token}, use_route: :door_mat
163
+ else
164
+ get :access_token, token_for: :big_ticket, token: token, use_route: :door_mat
165
+ end
166
+
167
+ expect(response).to have_http_status(200)
168
+ expect(response.body).to match(/Something looks wrong with your access token/)
169
+ expect(DoorMat::AccessToken.count).to eq(0)
170
+
171
+ token[0..7] = 'deadbeef'
172
+ if via_post
173
+ post :access_token_post, access_token: {token_for: :big_ticket, identifier: token}, use_route: :door_mat
174
+ else
175
+ get :access_token, token_for: :big_ticket, token: token, use_route: :door_mat
176
+ end
177
+
178
+ expect(response).to have_http_status(200)
179
+ expect(response.body).to match(/Something looks wrong with your access token/)
180
+ end
181
+
182
+ it 'it rejects a malformed, late or inexistent token request via post' do
183
+ reject_malformed_late_inexistent_token_request(via_post = true)
184
+ end
185
+
186
+ it 'it rejects a malformed, late or inexistent token request via get' do
187
+ reject_malformed_late_inexistent_token_request(via_post = false)
188
+ end
189
+
190
+ it 'raise an exception' do
191
+ admin = {email: Rails.application.secrets.admin_account_email, password: Rails.application.secrets.admin_account_pwd}
192
+ DoorMat::TestHelper.create_signed_up_actor_with_confirmed_email_address(admin[:email], admin[:password])
193
+
194
+ allow(DoorMat::PasswordLessSessionMailer).to receive(:send_token).and_raise(RuntimeError)
195
+ expect {
196
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"user1@example.com"}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
197
+ }.to raise_error(RuntimeError)
198
+ end
199
+
200
+ it 'rejects a submission where identifier and confirmation does not match' do
201
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"wrong_email@example.com"}, "commit"=>"Request access token", "token_for"=>:big_ticket}
202
+ expect(response.body).to match(/The identifier provided does not match the confirmation field/)
203
+ expect(response).to have_http_status(200)
204
+ end
205
+
206
+ it 'rejects a submission where identifier is blank' do
207
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"", "confirm_identifier"=>"user1@example.com"}, "commit"=>"Request access token", "token_for"=>:big_ticket}
208
+ expect(response.body).to match(/The identifier can not be blank/)
209
+ expect(response).to have_http_status(200)
210
+ end
211
+
212
+ it 'rejects a submission where identifier is not a valid address' do
213
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"invalid_identifier", "confirm_identifier"=>"user1@example.com"}, "commit"=>"Request access token", "token_for"=>:big_ticket}
214
+ expect(response.body).to match(/The identifier is expected to be a valid email address/)
215
+ expect(response).to have_http_status(200)
216
+ end
217
+
218
+ it 'rejects a submission where token_for is not valid' do
219
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"user1@example.com"}, "commit"=>"Request access token", "token_for"=>:invalid_token}
220
+ expect(response.body).to match(/Could not create a request token based on the information provided/)
221
+ expect(response).to have_http_status(200)
222
+ end
223
+
224
+ describe 'the public, private and remember me behavior' do
225
+
226
+ describe 'With default config' do
227
+
228
+ before(:context) do
229
+ reset_default_config
230
+ end
231
+ after (:context) do
232
+ reset_default_config
233
+ end
234
+
235
+ before(:example) do
236
+ admin = {email: Rails.application.secrets.admin_account_email, password: Rails.application.secrets.admin_account_pwd}
237
+ DoorMat::TestHelper.create_signed_up_actor_with_confirmed_email_address(admin[:email], admin[:password])
238
+ end
239
+
240
+ it 'requests public_computer without remember_me' do
241
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"user1@example.com", "is_public"=>"1", "remember_me"=>"0"}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
242
+ expect(DoorMat::AccessToken.first.public_computer?).to be true
243
+ end
244
+
245
+ it 'requests public_computer with remember_me' do
246
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"user1@example.com", "is_public"=>"1", "remember_me"=>"1"}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
247
+ expect(DoorMat::AccessToken.first.public_computer?).to be true
248
+ end
249
+
250
+ it 'requests private_computer without remember_me' do
251
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"user1@example.com", "is_public"=>"0", "remember_me"=>"0"}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
252
+ expect(DoorMat::AccessToken.first.private_computer?).to be true
253
+ end
254
+
255
+ it 'requests private_computer with remember_me' do
256
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"user1@example.com", "is_public"=>"0", "remember_me"=>"1"}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
257
+ expect(DoorMat::AccessToken.first.private_computer?).to be true
258
+ end
259
+
260
+ end
261
+
262
+
263
+ describe 'When remember_me is allowed only on a private computer' do
264
+
265
+ before(:context) do
266
+ reset_default_config
267
+ DoorMat.configuration.allow_remember_me_feature = true
268
+ end
269
+ after (:context) do
270
+ reset_default_config
271
+ end
272
+
273
+ before(:example) do
274
+ admin = {email: Rails.application.secrets.admin_account_email, password: Rails.application.secrets.admin_account_pwd}
275
+ DoorMat::TestHelper.create_signed_up_actor_with_confirmed_email_address(admin[:email], admin[:password])
276
+ end
277
+
278
+ it 'requests public_computer without remember_me' do
279
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"user1@example.com", "is_public"=>"1", "remember_me"=>"0"}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
280
+ expect(DoorMat::AccessToken.first.public_computer?).to be true
281
+ end
282
+
283
+ it 'requests public_computer with remember_me' do
284
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"user1@example.com", "is_public"=>"1", "remember_me"=>"1"}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
285
+ expect(DoorMat::AccessToken.first.public_computer?).to be true
286
+ end
287
+
288
+ it 'requests private_computer without remember_me' do
289
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"user1@example.com", "is_public"=>"0", "remember_me"=>"0"}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
290
+ expect(DoorMat::AccessToken.first.private_computer?).to be true
291
+ end
292
+
293
+ it 'requests private_computer with remember_me' do
294
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"user1@example.com", "is_public"=>"0", "remember_me"=>"1"}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
295
+ expect(DoorMat::AccessToken.first.remember_me?).to be true
296
+ end
297
+
298
+ end
299
+
300
+
301
+ describe 'When remember_me is allowed on both public and private computers' do
302
+
303
+ before(:context) do
304
+ reset_default_config
305
+ DoorMat.configuration.allow_remember_me_feature = true
306
+ DoorMat.configuration.remember_me_require_private_computer_confirmation = false
307
+ end
308
+ after (:context) do
309
+ reset_default_config
310
+ end
311
+
312
+ before(:example) do
313
+ admin = {email: Rails.application.secrets.admin_account_email, password: Rails.application.secrets.admin_account_pwd}
314
+ DoorMat::TestHelper.create_signed_up_actor_with_confirmed_email_address(admin[:email], admin[:password])
315
+ end
316
+
317
+ it 'requests public_computer without remember_me' do
318
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"user1@example.com", "is_public"=>"1", "remember_me"=>"0"}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
319
+ expect(DoorMat::AccessToken.first.public_computer?).to be true
320
+ end
321
+
322
+ it 'requests public_computer with remember_me' do
323
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"user1@example.com", "is_public"=>"1", "remember_me"=>"1"}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
324
+ expect(DoorMat::AccessToken.first.remember_me?).to be true
325
+ end
326
+
327
+ it 'requests private_computer without remember_me' do
328
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"user1@example.com", "is_public"=>"0", "remember_me"=>"0"}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
329
+ expect(DoorMat::AccessToken.first.private_computer?).to be true
330
+ end
331
+
332
+ it 'requests private_computer with remember_me' do
333
+ post :create, {"utf8"=>"✓", "access_token"=>{"identifier"=>"user1@example.com", "confirm_identifier"=>"user1@example.com", "is_public"=>"0", "remember_me"=>"1"}, "commit"=>"Request access token", "token_for"=>:big_ticket}, use_route: :main_app
334
+ expect(DoorMat::AccessToken.first.remember_me?).to be true
335
+ end
336
+
337
+ end
338
+
339
+ end
340
+
341
+ end
342
+
343
+ end
344
+ end