door_mat 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +2 -0
- data/Gemfile +3 -0
- data/MIT-LICENSE +20 -0
- data/README.md +88 -0
- data/Rakefile +32 -0
- data/app/assets/javascripts/door_mat/application.js +13 -0
- data/app/assets/stylesheets/door_mat/application.css +15 -0
- data/app/assets/stylesheets/scaffold.css +56 -0
- data/app/controllers/door_mat/activities_controller.rb +106 -0
- data/app/controllers/door_mat/application_controller.rb +14 -0
- data/app/controllers/door_mat/change_password_controller.rb +32 -0
- data/app/controllers/door_mat/forgot_passwords_controller.rb +57 -0
- data/app/controllers/door_mat/manage_email_controller.rb +61 -0
- data/app/controllers/door_mat/password_less_session_controller.rb +121 -0
- data/app/controllers/door_mat/reconfirm_password_controller.rb +27 -0
- data/app/controllers/door_mat/sessions_controller.rb +17 -0
- data/app/controllers/door_mat/sign_in_controller.rb +60 -0
- data/app/controllers/door_mat/sign_up_controller.rb +59 -0
- data/app/controllers/door_mat/static_controller.rb +5 -0
- data/app/mailers/door_mat/activity_mailer.rb +18 -0
- data/app/mailers/door_mat/password_less_session_mailer.rb +12 -0
- data/app/models/door_mat/access_token.rb +315 -0
- data/app/models/door_mat/activity.rb +14 -0
- data/app/models/door_mat/activity_confirm_email.rb +45 -0
- data/app/models/door_mat/activity_download_recovery_key.rb +30 -0
- data/app/models/door_mat/activity_reset_password.rb +47 -0
- data/app/models/door_mat/actor.rb +149 -0
- data/app/models/door_mat/change_password.rb +12 -0
- data/app/models/door_mat/email.rb +58 -0
- data/app/models/door_mat/forgot_password.rb +12 -0
- data/app/models/door_mat/membership.rb +42 -0
- data/app/models/door_mat/session.rb +315 -0
- data/app/models/door_mat/sign_in.rb +31 -0
- data/app/models/door_mat/sign_up.rb +17 -0
- data/app/views/door_mat/activity_mailer/confirm_email.html.erb +11 -0
- data/app/views/door_mat/activity_mailer/confirm_email.text.erb +7 -0
- data/app/views/door_mat/activity_mailer/reset_password.html.erb +11 -0
- data/app/views/door_mat/activity_mailer/reset_password.text.erb +7 -0
- data/app/views/door_mat/change_password/new.html.erb +22 -0
- data/app/views/door_mat/forgot_passwords/choose_new_password.html.erb +34 -0
- data/app/views/door_mat/forgot_passwords/new.html.erb +14 -0
- data/app/views/door_mat/helpers/_errors_if_any.html.erb +10 -0
- data/app/views/door_mat/manage_email/new.html.erb +14 -0
- data/app/views/door_mat/password_less_session/access_token.html.erb +16 -0
- data/app/views/door_mat/password_less_session/new.html.erb +34 -0
- data/app/views/door_mat/password_less_session_mailer/send_token.html.erb +11 -0
- data/app/views/door_mat/password_less_session_mailer/send_token.text.erb +7 -0
- data/app/views/door_mat/reconfirm_password/new.html.erb +12 -0
- data/app/views/door_mat/sign_in/new.html.erb +30 -0
- data/app/views/door_mat/sign_up/new.html.erb +24 -0
- data/app/views/door_mat/static/add_email_success.html.erb +5 -0
- data/app/views/door_mat/static/change_password_success.html.erb +2 -0
- data/app/views/door_mat/static/confirm_email_success.html.erb +2 -0
- data/app/views/door_mat/static/email_confirmation_required.html.erb +17 -0
- data/app/views/door_mat/static/forgot_password_verification_mail_sent.html.erb +2 -0
- data/app/views/door_mat/static/reconfirm_password_success.html.erb +4 -0
- data/app/views/door_mat/static/sign_in_success.html.erb +5 -0
- data/app/views/door_mat/static/sign_out_success.html.erb +5 -0
- data/app/views/door_mat/static/sign_up_success.html.erb +4 -0
- data/bin/rails +12 -0
- data/config/locales/en.yml +73 -0
- data/config/routes.rb +48 -0
- data/db/migrate/20140616234935_create_door_mat_actors.rb +23 -0
- data/db/migrate/20140617233357_create_door_mat_sessions.rb +17 -0
- data/db/migrate/20140630043202_create_door_mat_emails.rb +12 -0
- data/db/migrate/20140702045729_create_door_mat_activities.rb +14 -0
- data/db/migrate/20141115183045_create_door_mat_access_tokens.rb +17 -0
- data/db/migrate/20141121191824_create_door_mat_memberships.rb +14 -0
- data/db/migrate/20150910182126_rename_session_guid_column.rb +5 -0
- data/db/migrate/20150918210831_add_access_token_rating_column.rb +5 -0
- data/door_mat.gemspec +37 -0
- data/lib/door_mat.rb +20 -0
- data/lib/door_mat/attr_asymmetric_store.rb +82 -0
- data/lib/door_mat/attr_symmetric_store.rb +82 -0
- data/lib/door_mat/configuration.rb +193 -0
- data/lib/door_mat/controller.rb +117 -0
- data/lib/door_mat/crypto.rb +49 -0
- data/lib/door_mat/crypto/asymmetric_store.rb +77 -0
- data/lib/door_mat/crypto/fast_hash.rb +17 -0
- data/lib/door_mat/crypto/password_hash.rb +39 -0
- data/lib/door_mat/crypto/secure_compare.rb +23 -0
- data/lib/door_mat/crypto/symmetric_store.rb +68 -0
- data/lib/door_mat/engine.rb +23 -0
- data/lib/door_mat/process/actor_password_change.rb +65 -0
- data/lib/door_mat/process/actor_sign_in.rb +38 -0
- data/lib/door_mat/process/actor_sign_up.rb +39 -0
- data/lib/door_mat/process/create_new_anonymous_actor.rb +36 -0
- data/lib/door_mat/process/manage_email.rb +42 -0
- data/lib/door_mat/process/reset_password.rb +50 -0
- data/lib/door_mat/regex.rb +17 -0
- data/lib/door_mat/test_helper.rb +58 -0
- data/lib/door_mat/url_protocol.rb +9 -0
- data/lib/door_mat/version.rb +3 -0
- data/lib/tasks/door_mat_tasks.rake +31 -0
- data/spec/controllers/door_mat/activities_controller_spec.rb +70 -0
- data/spec/controllers/door_mat/forgot_passwords_controller_spec.rb +57 -0
- data/spec/controllers/door_mat/manage_email_spec.rb +181 -0
- data/spec/controllers/door_mat/password_less_session_controller_spec.rb +344 -0
- data/spec/controllers/door_mat/sign_in_controller_spec.rb +211 -0
- data/spec/controllers/door_mat/sign_up_controller_spec.rb +90 -0
- data/spec/factories/door_mat_access_tokens.rb +6 -0
- data/spec/factories/door_mat_activitiess.rb +6 -0
- data/spec/factories/door_mat_actors.rb +23 -0
- data/spec/factories/door_mat_emails.rb +14 -0
- data/spec/factories/door_mat_memberships.rb +6 -0
- data/spec/factories/door_mat_sessions.rb +24 -0
- data/spec/features/password_less_session_spec.rb +165 -0
- data/spec/features/remember_me_spec.rb +672 -0
- data/spec/features/session_spec.rb +336 -0
- data/spec/lib/attr_store_spec.rb +237 -0
- data/spec/lib/crypto_spec.rb +130 -0
- data/spec/lib/process_spec.rb +159 -0
- data/spec/models/door_mat/access_token_spec.rb +134 -0
- data/spec/models/door_mat/activity_spec.rb +38 -0
- data/spec/models/door_mat/actor_spec.rb +56 -0
- data/spec/models/door_mat/email_spec.rb +25 -0
- data/spec/models/door_mat/session_spec.rb +69 -0
- data/spec/spec_helper.rb +223 -0
- data/spec/support/timecop/timecop_helper.rb +52 -0
- data/spec/test_app/README.rdoc +28 -0
- data/spec/test_app/Rakefile +6 -0
- data/spec/test_app/app/assets/javascripts/application.js +13 -0
- data/spec/test_app/app/assets/stylesheets/application.css +15 -0
- data/spec/test_app/app/controllers/account_controller.rb +28 -0
- data/spec/test_app/app/controllers/application_controller.rb +10 -0
- data/spec/test_app/app/controllers/password_less_sample_controller.rb +56 -0
- data/spec/test_app/app/controllers/static_controller.rb +7 -0
- data/spec/test_app/app/helpers/account_helper.rb +2 -0
- data/spec/test_app/app/helpers/application_helper.rb +2 -0
- data/spec/test_app/app/models/game.rb +62 -0
- data/spec/test_app/app/models/shared_data.rb +4 -0
- data/spec/test_app/app/models/shared_key.rb +8 -0
- data/spec/test_app/app/models/user_detail.rb +7 -0
- data/spec/test_app/app/views/account/show.html.erb +133 -0
- data/spec/test_app/app/views/door_mat/static/sign_out_success.html.erb +7 -0
- data/spec/test_app/app/views/layouts/application.html.erb +20 -0
- data/spec/test_app/app/views/password_less_sample/draw_results.html.erb +6 -0
- data/spec/test_app/app/views/password_less_sample/final_result.html.erb +7 -0
- data/spec/test_app/app/views/password_less_sample/play_game.html.erb +5 -0
- data/spec/test_app/app/views/password_less_sample/show_loosing_door.html.erb +10 -0
- data/spec/test_app/app/views/static/index.html.erb +12 -0
- data/spec/test_app/app/views/static/only_confirmed_email_allowed.html.erb +10 -0
- data/spec/test_app/app/views/static/page_that_require_password_reconfirmation.html.erb +16 -0
- data/spec/test_app/app/views/static/session_protected_page.html.erb +32 -0
- data/spec/test_app/bin/bundle +3 -0
- data/spec/test_app/bin/rails +4 -0
- data/spec/test_app/bin/rake +4 -0
- data/spec/test_app/config.ru +4 -0
- data/spec/test_app/config/application.rb +29 -0
- data/spec/test_app/config/boot.rb +5 -0
- data/spec/test_app/config/database.yml +25 -0
- data/spec/test_app/config/environment.rb +19 -0
- data/spec/test_app/config/environments/development.rb +50 -0
- data/spec/test_app/config/environments/production.rb +83 -0
- data/spec/test_app/config/environments/test.rb +48 -0
- data/spec/test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/test_app/config/initializers/cookies_serializer.rb +3 -0
- data/spec/test_app/config/initializers/door_mat.rb +72 -0
- data/spec/test_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/test_app/config/initializers/inflections.rb +16 -0
- data/spec/test_app/config/initializers/mime_types.rb +4 -0
- data/spec/test_app/config/initializers/session_store.rb +3 -0
- data/spec/test_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/test_app/config/locales/en.yml +23 -0
- data/spec/test_app/config/routes.rb +42 -0
- data/spec/test_app/config/secrets.yml +31 -0
- data/spec/test_app/db/migrate/20140717182813_create_user_details.rb +10 -0
- data/spec/test_app/db/migrate/20140908225256_create_shared_data.rb +10 -0
- data/spec/test_app/db/migrate/20140908225604_create_shared_keys.rb +11 -0
- data/spec/test_app/db/migrate/20141121190714_create_games.rb +10 -0
- data/spec/test_app/public/404.html +67 -0
- data/spec/test_app/public/422.html +67 -0
- data/spec/test_app/public/500.html +66 -0
- data/spec/test_app/public/favicon.ico +0 -0
- metadata +552 -0
checksums.yaml
ADDED
@@ -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
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -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.
|
data/Rakefile
ADDED
@@ -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
|