door_mat 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ad774be28584db37c0e422495fae8e21d1a0b9a2
4
+ data.tar.gz: cc7a4ed22545af0484c9fd9835afcabe478d06aa
5
+ SHA512:
6
+ metadata.gz: b0eae2b29f15aa1f50b64e4e3a2e08ad392c8d98a8ffbea10dec2392f211c85d244b929d871026578445d9862ccee8ff06ff80e969d1ab42f02db700c2d4c092
7
+ data.tar.gz: 033e66535d3edc70d5f8e782fc36cd607eae95ff43495593a7111336ceeae0c5738043fab7461ffe568ff66cca13a4a42c7511d6e563c099596c0453d093bb16
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,20 @@
1
+ Copyright 2014 Luc Lussier
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,88 @@
1
+ # DoorMat
2
+
3
+ Keeping keys safe since front doors have locks...
4
+
5
+
6
+ ### What is the DoorMat library?
7
+
8
+ DoorMat is a Rails Engine that provides a solution for both user authentication and the encryption of user information. It aims to offer safe defaults so you can get going with what your website is really about.
9
+
10
+ Although DoorMat is flexible and supports a variety of information sharing scenarios, its most basic configuration is such that _in the normal course of business_, the system operator does not have access to the user information protected by the encrypted store. The impact of this feature is that users must upload a recovery key file in order to reset their password should they forget it.
11
+
12
+
13
+ ### Security
14
+
15
+ #### Read me first!
16
+ **Disclaimer**: DoorMat is a fairly young and experimental library that could greatly benefit from the scrutiny of many eyes. Although care and efforts were taken while crafting this library, there is no doubt that it will contain various bugs. _Proceed with caution!_
17
+
18
+ That being said, DoorMat aims to cover the basics and set sensible defaults while allowing customization.
19
+
20
+ #### Batteries included
21
+ DoorMat seeks to provide reasonable default configuration values for session management and data encryption. Many behaviour settings are biased toward security rather than a smooth user experience and may need to be relaxed depending on your site's security requirements.
22
+
23
+ Although the initial default values may need to be updated, there should not be a need for the new user to select adequate values in order to harden the system. Rather, it should be secure by default and later customized to provide a better user experience.
24
+
25
+ #### Crunchy on the Outside _and_ the Inside
26
+ The reason for this emphasis is that although data theft by external actors get a lot of visibility in the press and makes for sensational news, [insider threats outrank external attacks](https://securityintelligence.com/the-threat-is-coming-from-inside-the-network/).
27
+
28
+ One aspect of user data security addressed by DoorMat is that _in the normal course of business_, with the engine running in a `RAILS_ENV=production` environment using unaltered source code, the user information protected by the symmetric store is not accessible to the site operator.
29
+
30
+ This means that by default, when a user creates an account, the site operator or any individual that gains access to the database cannot simply query the emails table to harvest user addresses. Each user's email address is encrypted using a key derived from their password.
31
+
32
+
33
+ ### Features
34
+
35
+ DoorMat currently provides the following features out of the box:
36
+
37
+ User side features
38
+ - User account sign-up
39
+ - Email address confirmation
40
+ - Manage account email address (add, remove) for an account
41
+ - Change password
42
+ - Download password recovery key file
43
+ - Reset forgotten password (using the recovery key file)
44
+ - Public / private computer selection at login time
45
+ - Remember me feature when a session is opened from a private computer
46
+ - Terminate other active sessions (so you can remotely kill that session you forgot to close on the public library computer)
47
+
48
+ System side features
49
+ - Standard email / password based accounts
50
+ - Alternative password less accounts with access control based on security tokens sent to users email address
51
+ - User information stores using symmetric encryption. For password secured accounts only
52
+ - Secret sharing store using asymmetric encryption
53
+ - Before / after hooks for various user activities: sign up/in/out, etc.
54
+ - Access restriction filters
55
+ - Only allow access to sessions from confirmed email address
56
+ - Require user to re-enter password for access to sensitive routes
57
+ - Easy to override defaults
58
+ - Redirection after user activity success / failure
59
+ - Session / remember me expiration delay for public / private computer selection
60
+ - Maximum number of emails per account
61
+ - Maximum number of accounts a single email can be associated with (aka server side plausible deniability)
62
+ - etc.
63
+
64
+
65
+ ### Usage
66
+
67
+ Run tests with `bundle exec rspec` and set `COVERAGE=true` to generate the coverage report after setting up the test database with `RAILS_ENV=test bundle exec rake db:drop db:create db:migrate`.
68
+
69
+ See `spec/test_app` for a sample application illustrating the various DoorMat features. You can `bundle exec rails server -p3001` to run a local instance.
70
+
71
+ You will also need to have [MailCatcher](https://mailcatcher.me/) running so you can confirm the email address you register with and to receive password less access tokens.
72
+ Point one browser tab to `http://localhost:1080` to access your local email and a second one to `http://localhost:3001` to interact with the test application.
73
+
74
+ Further sample usage will be released shortly!
75
+
76
+
77
+ ### Gem Version History
78
+
79
+ **0.0.5 - Why so serious?** (April 4, 2016)
80
+
81
+ * Initial public release.
82
+
83
+
84
+ ### License
85
+
86
+ Copyright © 2016 Luc Lussier
87
+
88
+ Released under the MIT license. See [MIT-LICENSE](MIT-LICENSE) for details.
@@ -0,0 +1,32 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'DoorMat'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/test_app/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ Dir[File.join(File.dirname(__FILE__), 'tasks/**/*.rake')].each {|f| load f }
25
+
26
+ require 'rspec/core'
27
+ require 'rspec/core/rake_task'
28
+
29
+ desc "Run all specs in spec directory (excluding plugin specs)"
30
+ RSpec::Core::RakeTask.new(:spec => 'app:db:test:prepare')
31
+
32
+ task :default => :spec
@@ -0,0 +1,13 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require_tree .
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,56 @@
1
+ body { background-color: #fff; color: #333; }
2
+
3
+ body, p, ol, ul, td {
4
+ font-family: verdana, arial, helvetica, sans-serif;
5
+ font-size: 13px;
6
+ line-height: 18px;
7
+ }
8
+
9
+ pre {
10
+ background-color: #eee;
11
+ padding: 10px;
12
+ font-size: 11px;
13
+ }
14
+
15
+ a { color: #000; }
16
+ a:visited { color: #666; }
17
+ a:hover { color: #fff; background-color:#000; }
18
+
19
+ div.field, div.actions {
20
+ margin-bottom: 10px;
21
+ }
22
+
23
+ #notice {
24
+ color: green;
25
+ }
26
+
27
+ .field_with_errors {
28
+ padding: 2px;
29
+ background-color: red;
30
+ display: table;
31
+ }
32
+
33
+ #error_explanation {
34
+ width: 450px;
35
+ border: 2px solid red;
36
+ padding: 7px;
37
+ padding-bottom: 0;
38
+ margin-bottom: 20px;
39
+ background-color: #f0f0f0;
40
+ }
41
+
42
+ #error_explanation h2 {
43
+ text-align: left;
44
+ font-weight: bold;
45
+ padding: 5px 5px 5px 15px;
46
+ font-size: 12px;
47
+ margin: -7px;
48
+ margin-bottom: 0px;
49
+ background-color: #c00;
50
+ color: #fff;
51
+ }
52
+
53
+ #error_explanation ul li {
54
+ font-size: 12px;
55
+ list-style: square;
56
+ }
@@ -0,0 +1,106 @@
1
+ module DoorMat
2
+ class ActivitiesController < DoorMat::ApplicationController
3
+ before_action :require_password_reconfirm
4
+ before_action :require_confirmed_email, except: [:resend_email_confirmation, :confirm_email]
5
+ before_action :update_session_last_activity_time
6
+
7
+ def resend_email_confirmation
8
+ actor = DoorMat::Session.current_session.actor
9
+ encoded_email = params[:email]
10
+
11
+ email = actor.email_from_urlsafe_encoded(encoded_email)
12
+ if email.blank?
13
+ redirect_to config_url_redirect(:resend_email_confirmation_redirect_url)
14
+ else
15
+ if email.not_confirmed?
16
+ DoorMat::ActivityConfirmEmail.for(email, self)
17
+ redirect_to config_url_redirect(:resend_email_confirmation_redirect_url)
18
+ else
19
+ redirect_to config_url_redirect(:confirm_email_success_url)
20
+ end
21
+ end
22
+ end
23
+
24
+ # :email is a Base64.urlsafe_encode64 of a user email address
25
+ def confirm_email
26
+ before_confirm_email
27
+
28
+ actor = DoorMat::Session.current_session.actor
29
+ token = params[:token]
30
+ encoded_address = params[:email]
31
+
32
+ actor.with_lock do
33
+ actor.confirm_email_activities.each do |activity|
34
+ if activity.input_valid?(token, encoded_address)
35
+ if actor.has_primary_email?
36
+ activity.email.confirmed!
37
+ else
38
+ activity.email.primary!
39
+ end
40
+ activity.done!
41
+ flash[:notice] = "Email was confirmed."
42
+
43
+ redirect_to config_url_redirect(:confirm_email_success_url)
44
+ after_confirm_email(activity.email)
45
+ return
46
+ end
47
+ end
48
+ end
49
+
50
+ after_failed_confirm_email
51
+ lockdown(log_message: 'ERROR: failed request to confirm_email')
52
+ end
53
+
54
+ def download_recovery_key
55
+ before_download_recovery_key
56
+
57
+ actor = DoorMat::Session.current_session.actor
58
+ token = params[:token]
59
+ disposition = params[:disposition]
60
+
61
+ disposition = 'attachment' unless disposition.to_s == 'inline'
62
+
63
+ actor.with_lock do
64
+ actor.download_recovery_key_activities.each do |activity|
65
+ if activity.input_valid?(token)
66
+
67
+ recovery_key = DoorMat::Session.current_session.package_recovery_key
68
+
69
+ send_data recovery_key, filename: "recovery_key_#{Date.current.strftime("%Y%m%d")}.txt", disposition: disposition
70
+
71
+ activity.done!
72
+ flash[:notice] = "Keep this recovery key file safely, you will need it to recover your data in case you forget your password."
73
+ after_download_recovery_key
74
+ return
75
+ end
76
+ end
77
+ end
78
+
79
+ after_failed_download_recovery_key
80
+ lockdown(log_message: 'ERROR: failed request to download_recovery_key')
81
+ end
82
+
83
+ private
84
+
85
+ def before_confirm_email
86
+ DoorMat.configuration.event_hook_before_confirm_email.each {|prc| prc.call}
87
+ end
88
+ def after_confirm_email(email)
89
+ DoorMat.configuration.event_hook_after_confirm_email.each {|prc| prc.call(email)}
90
+ end
91
+ def after_failed_confirm_email
92
+ DoorMat.configuration.event_hook_after_failed_confirm_email.each {|prc| prc.call}
93
+ end
94
+
95
+ def before_download_recovery_key
96
+ DoorMat.configuration.event_hook_before_download_recovery_key.each {|prc| prc.call}
97
+ end
98
+ def after_download_recovery_key
99
+ DoorMat.configuration.event_hook_after_download_recovery_key.each {|prc| prc.call}
100
+ end
101
+ def after_failed_download_recovery_key
102
+ DoorMat.configuration.event_hook_after_failed_download_recovery_key.each {|prc| prc.call}
103
+ end
104
+
105
+ end
106
+ end
@@ -0,0 +1,14 @@
1
+ module DoorMat
2
+ class ApplicationController < ActionController::Base
3
+
4
+ # Make the engine use the main_app layouts/application file and helpers
5
+ layout 'layouts/application'
6
+ helper Rails.application.helpers
7
+
8
+ include DoorMat::Controller
9
+ before_action :require_valid_session
10
+
11
+ protect_from_forgery with: :exception
12
+
13
+ end
14
+ end
@@ -0,0 +1,32 @@
1
+ module DoorMat
2
+ class ChangePasswordController < DoorMat::ApplicationController
3
+ before_action :require_confirmed_email
4
+ before_action :update_session_last_activity_time
5
+
6
+ def new
7
+ @change_password = DoorMat::ChangePassword.new
8
+ end
9
+
10
+ def create
11
+ @change_password = DoorMat::ChangePassword.new(change_password_params)
12
+ actor = DoorMat::Session.current_session.actor
13
+
14
+ if @change_password.valid? && DoorMat::Process::ActorPasswordChange.with(actor, @change_password.new_password, @change_password.old_password)
15
+ DoorMat::Session.current_session.set_up(cookies)
16
+ flash[:notice] = I18n.t('door_mat.change_password.success')
17
+
18
+ redirect_to config_url_redirect(:change_password_success_url)
19
+ else
20
+ flash[:alert] = I18n.t('door_mat.change_password.failed')
21
+ render :new
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def change_password_params
28
+ params.require(:change_password).permit(:old_password, :new_password, :new_password_confirmation)
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,57 @@
1
+ module DoorMat
2
+ class ForgotPasswordsController < DoorMat::ApplicationController
3
+ skip_before_action :require_valid_session, :only => [:new, :create, :choose_new_password, :reset_password]
4
+
5
+ def new
6
+ @forgot_password = DoorMat::ForgotPassword.new
7
+ end
8
+
9
+ # :email is a Base64.urlsafe_encode64 of a user email address
10
+ def create
11
+ @forgot_password = DoorMat::ForgotPassword.new(forgot_password_params)
12
+ @forgot_password.password = @forgot_password.password_confirmation = '-'
13
+
14
+ if @forgot_password.valid?
15
+ DoorMat::Process::ResetPassword.for(@forgot_password.email, self)
16
+
17
+ # No matter what, requester gets the same response
18
+ redirect_to config_url_redirect(:forgot_password_verification_mail_sent_url)
19
+ else
20
+ render :new
21
+ end
22
+ end
23
+
24
+ def choose_new_password
25
+ @forgot_password = DoorMat::ForgotPassword.new(choose_new_password_params)
26
+ @forgot_password.email = DoorMat::Email.decode_urlsafe(@forgot_password.email)
27
+ end
28
+
29
+ def reset_password
30
+ @forgot_password = DoorMat::ForgotPassword.new(reset_password_params)
31
+ if @forgot_password.valid?
32
+ if DoorMat::Process::ResetPassword.with(@forgot_password)
33
+ redirect_to door_mat.sign_in_url
34
+ else
35
+ flash[:alert] = I18n.t('door_mat.forgot_password.make_new_request')
36
+ redirect_to door_mat.forgot_password_url
37
+ end
38
+
39
+ else
40
+ render :choose_new_password
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def forgot_password_params
47
+ params.require(:forgot_password).permit(:email)
48
+ end
49
+ def choose_new_password_params
50
+ params.permit(:email, :token)
51
+ end
52
+ def reset_password_params
53
+ params.require(:forgot_password).permit(:email, :password, :password_confirmation, :recovery_key, :token)
54
+ end
55
+
56
+ end
57
+ end