devise-security 0.11.0
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.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.gitignore +38 -0
- data/.rubocop.yml +42 -0
- data/.travis.yml +14 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +199 -0
- data/LICENSE.txt +20 -0
- data/README.md +263 -0
- data/Rakefile +26 -0
- data/app/controllers/devise/paranoid_verification_code_controller.rb +42 -0
- data/app/controllers/devise/password_expired_controller.rb +48 -0
- data/app/views/devise/paranoid_verification_code/show.html.erb +10 -0
- data/app/views/devise/password_expired/show.html.erb +16 -0
- data/config/locales/de.yml +16 -0
- data/config/locales/en.yml +17 -0
- data/config/locales/es.yml +17 -0
- data/config/locales/it.yml +10 -0
- data/devise-security.gemspec +34 -0
- data/lib/devise-security.rb +106 -0
- data/lib/devise-security/controllers/helpers.rb +96 -0
- data/lib/devise-security/hooks/expirable.rb +10 -0
- data/lib/devise-security/hooks/paranoid_verification.rb +5 -0
- data/lib/devise-security/hooks/password_expirable.rb +5 -0
- data/lib/devise-security/hooks/session_limitable.rb +27 -0
- data/lib/devise-security/models/database_authenticatable_patch.rb +26 -0
- data/lib/devise-security/models/expirable.rb +120 -0
- data/lib/devise-security/models/old_password.rb +4 -0
- data/lib/devise-security/models/paranoid_verification.rb +35 -0
- data/lib/devise-security/models/password_archivable.rb +80 -0
- data/lib/devise-security/models/password_expirable.rb +67 -0
- data/lib/devise-security/models/secure_validatable.rb +100 -0
- data/lib/devise-security/models/security_questionable.rb +18 -0
- data/lib/devise-security/models/session_limitable.rb +21 -0
- data/lib/devise-security/orm/active_record.rb +20 -0
- data/lib/devise-security/patches.rb +21 -0
- data/lib/devise-security/patches/confirmations_controller_captcha.rb +21 -0
- data/lib/devise-security/patches/confirmations_controller_security_question.rb +25 -0
- data/lib/devise-security/patches/controller_captcha.rb +17 -0
- data/lib/devise-security/patches/controller_security_question.rb +20 -0
- data/lib/devise-security/patches/passwords_controller_captcha.rb +20 -0
- data/lib/devise-security/patches/passwords_controller_security_question.rb +24 -0
- data/lib/devise-security/patches/registrations_controller_captcha.rb +33 -0
- data/lib/devise-security/patches/sessions_controller_captcha.rb +24 -0
- data/lib/devise-security/patches/unlocks_controller_captcha.rb +20 -0
- data/lib/devise-security/patches/unlocks_controller_security_question.rb +24 -0
- data/lib/devise-security/rails.rb +17 -0
- data/lib/devise-security/routes.rb +17 -0
- data/lib/devise-security/schema.rb +59 -0
- data/lib/devise-security/version.rb +3 -0
- data/lib/generators/devise-security/install_generator.rb +26 -0
- data/lib/generators/templates/devise-security.rb +38 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/controllers/application_controller.rb +2 -0
- data/test/dummy/app/controllers/captcha/sessions_controller.rb +3 -0
- data/test/dummy/app/controllers/foos_controller.rb +0 -0
- data/test/dummy/app/controllers/security_question/unlocks_controller.rb +3 -0
- data/test/dummy/app/models/.gitkeep +0 -0
- data/test/dummy/app/models/captcha_user.rb +5 -0
- data/test/dummy/app/models/secure_user.rb +3 -0
- data/test/dummy/app/models/security_question_user.rb +6 -0
- data/test/dummy/app/models/user.rb +5 -0
- data/test/dummy/app/views/foos/index.html.erb +0 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +24 -0
- data/test/dummy/config/boot.rb +6 -0
- data/test/dummy/config/database.yml +7 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/test.rb +27 -0
- data/test/dummy/config/initializers/devise.rb +9 -0
- data/test/dummy/config/initializers/migration_class.rb +6 -0
- data/test/dummy/config/routes.rb +10 -0
- data/test/dummy/config/secrets.yml +3 -0
- data/test/dummy/db/migrate/20120508165529_create_tables.rb +33 -0
- data/test/dummy/db/migrate/20150402165590_add_verification_columns.rb +11 -0
- data/test/dummy/db/migrate/20150407162345_add_verification_attempt_column.rb +9 -0
- data/test/dummy/db/migrate/20160320162345_add_security_questions_fields.rb +8 -0
- data/test/test_captcha_controller.rb +58 -0
- data/test/test_helper.rb +13 -0
- data/test/test_install_generator.rb +16 -0
- data/test/test_paranoid_verification.rb +124 -0
- data/test/test_password_archivable.rb +61 -0
- data/test/test_password_expirable.rb +32 -0
- data/test/test_password_expired_controller.rb +29 -0
- data/test/test_secure_validatable.rb +85 -0
- data/test/test_security_question_controller.rb +60 -0
- metadata +315 -0
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
$:.unshift File.join(File.dirname(__FILE__), 'lib')
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler'
|
4
|
+
require 'rake/testtask'
|
5
|
+
require 'rdoc/task'
|
6
|
+
require 'devise-security/version'
|
7
|
+
|
8
|
+
desc 'Default: Run DeviseSecurity unit tests'
|
9
|
+
task default: :test
|
10
|
+
|
11
|
+
Rake::TestTask.new(:test) do |t|
|
12
|
+
t.libs << 'lib'
|
13
|
+
t.libs << 'test'
|
14
|
+
t.test_files = FileList['test/*test*.rb']
|
15
|
+
t.verbose = true
|
16
|
+
t.warning = false
|
17
|
+
end
|
18
|
+
|
19
|
+
Rake::RDocTask.new do |rdoc|
|
20
|
+
version = DeviseSecurity::VERSION.dup
|
21
|
+
|
22
|
+
rdoc.rdoc_dir = 'rdoc'
|
23
|
+
rdoc.title = "devise-security #{version}"
|
24
|
+
rdoc.rdoc_files.include('README*')
|
25
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
26
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Devise::ParanoidVerificationCodeController < DeviseController
|
2
|
+
skip_before_action :handle_paranoid_verification
|
3
|
+
prepend_before_action :authenticate_scope!, :only => [:show, :update]
|
4
|
+
|
5
|
+
def show
|
6
|
+
if !resource.nil? && resource.need_paranoid_verification?
|
7
|
+
respond_with(resource)
|
8
|
+
else
|
9
|
+
redirect_to :root
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def update
|
14
|
+
if resource.verify_code(resource_params[:paranoid_verification_code])
|
15
|
+
warden.session(scope)['paranoid_verify'] = false
|
16
|
+
set_flash_message :notice, :updated
|
17
|
+
bypass_sign_in resource, scope: scope
|
18
|
+
redirect_to stored_location_for(scope) || :root
|
19
|
+
else
|
20
|
+
respond_with(resource, action: :show)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def resource_params
|
27
|
+
if params.respond_to?(:permit)
|
28
|
+
params.require(resource_name).permit(:paranoid_verification_code)
|
29
|
+
else
|
30
|
+
params[scope].slice(:paranoid_verification_code)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def scope
|
35
|
+
resource_name.to_sym
|
36
|
+
end
|
37
|
+
|
38
|
+
def authenticate_scope!
|
39
|
+
send(:"authenticate_#{resource_name}!")
|
40
|
+
self.resource = send("current_#{resource_name}")
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
class Devise::PasswordExpiredController < DeviseController
|
2
|
+
skip_before_action :handle_password_change
|
3
|
+
before_action :skip_password_change, only: [:show, :update]
|
4
|
+
prepend_before_action :authenticate_scope!, :only => [:show, :update]
|
5
|
+
|
6
|
+
def show
|
7
|
+
respond_with(resource)
|
8
|
+
end
|
9
|
+
|
10
|
+
def update
|
11
|
+
resource.extend(Devise::Models::DatabaseAuthenticatablePatch)
|
12
|
+
if resource.update_with_password(resource_params)
|
13
|
+
warden.session(scope)['password_expired'] = false
|
14
|
+
set_flash_message :notice, :updated
|
15
|
+
bypass_sign_in resource, scope: scope
|
16
|
+
redirect_to stored_location_for(scope) || :root
|
17
|
+
else
|
18
|
+
clean_up_passwords(resource)
|
19
|
+
respond_with(resource, action: :show)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def skip_password_change
|
26
|
+
return if !resource.nil? && resource.need_change_password?
|
27
|
+
redirect_to :root
|
28
|
+
end
|
29
|
+
|
30
|
+
def resource_params
|
31
|
+
permitted_params = [:current_password, :password, :password_confirmation]
|
32
|
+
|
33
|
+
if params.respond_to?(:permit)
|
34
|
+
params.require(resource_name).permit(*permitted_params)
|
35
|
+
else
|
36
|
+
params[scope].slice(*permitted_params)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def scope
|
41
|
+
resource_name.to_sym
|
42
|
+
end
|
43
|
+
|
44
|
+
def authenticate_scope!
|
45
|
+
send(:"authenticate_#{resource_name}!")
|
46
|
+
self.resource = send("current_#{resource_name}")
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<h2>Submit verification code</h2>
|
2
|
+
|
3
|
+
<%= form_for(resource, :as => resource_name, :url => [resource_name, :paranoid_verification_code], :html => { :method => :put }) do |f| %>
|
4
|
+
<%= devise_error_messages! %>
|
5
|
+
|
6
|
+
<p><%= f.label :paranoid_verification_code, 'Verification code' %><br />
|
7
|
+
<%= f.text_field :paranoid_verification_code, value: '' %></p>
|
8
|
+
|
9
|
+
<p><%= f.submit "Submit" %></p>
|
10
|
+
<% end %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<h2>Renew your password</h2>
|
2
|
+
|
3
|
+
<%= form_for(resource, :as => resource_name, :url => [resource_name, :password_expired], :html => { :method => :put }) do |f| %>
|
4
|
+
<%= devise_error_messages! %>
|
5
|
+
|
6
|
+
<p><%= f.label :current_password, "Current password" %><br />
|
7
|
+
<%= f.password_field :current_password %></p>
|
8
|
+
|
9
|
+
<p><%= f.label :password, "New password" %><br />
|
10
|
+
<%= f.password_field :password %></p>
|
11
|
+
|
12
|
+
<p><%= f.label :password_confirmation, "Confirm new password" %><br />
|
13
|
+
<%= f.password_field :password_confirmation %></p>
|
14
|
+
|
15
|
+
<p><%= f.submit "Change my password" %></p>
|
16
|
+
<% end %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
de:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
taken_in_past: "wurde bereits in der Vergangenheit verwendet!"
|
5
|
+
equal_to_current_password: "darf nicht dem aktuellen Passwort entsprechen!"
|
6
|
+
password_format: "müssen große, kleine Buchstaben und Ziffern enthalten"
|
7
|
+
devise:
|
8
|
+
invalid_captcha: "Die Captchaeingabe ist nicht gültig!"
|
9
|
+
paranoid_verify:
|
10
|
+
code_required: "Bitte geben Sie den Code unser Support-Team zur Verfügung gestellt"
|
11
|
+
password_expired:
|
12
|
+
updated: "Das neue Passwort wurde übernommen."
|
13
|
+
change_required: "Ihr Passwort ist abgelaufen. Bitte vergeben sie ein neues Passwort!"
|
14
|
+
failure:
|
15
|
+
session_limited: 'Ihre Anmeldedaten wurden in einem anderen Browser genutzt. Bitte melden Sie sich erneut an, um in diesem Browser fortzufahren.'
|
16
|
+
expired: 'Ihr Account ist aufgrund zu langer Inaktiviät abgelaufen. Bitte kontaktieren Sie den Administrator.'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
en:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
taken_in_past: "was used previously."
|
5
|
+
equal_to_current_password: "must be different than the current password."
|
6
|
+
password_format: "must contain big, small letters and digits"
|
7
|
+
devise:
|
8
|
+
invalid_captcha: "The captcha input was invalid."
|
9
|
+
invalid_security_question: "The security question answer was invalid."
|
10
|
+
paranoid_verify:
|
11
|
+
code_required: "Please enter the code our support team provided"
|
12
|
+
password_expired:
|
13
|
+
updated: "Your new password is saved."
|
14
|
+
change_required: "Your password is expired. Please renew your password."
|
15
|
+
failure:
|
16
|
+
session_limited: 'Your login credentials were used in another browser. Please sign in again to continue in this browser.'
|
17
|
+
expired: 'Your account has expired due to inactivity. Please contact the site administrator.'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
es:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
taken_in_past: "la contraseña fue usada previamente, favor elegir otra."
|
5
|
+
equal_to_current_password: "tiene que ser diferente a la contraseña actual."
|
6
|
+
password_format: "tiene que contener mayúsculas, minúsculas y digitos "
|
7
|
+
devise:
|
8
|
+
invalid_captcha: "El captcha ingresado es inválido."
|
9
|
+
invalid_security_question: "La respuesta a la pregunta de suguridad fue incorrecta."
|
10
|
+
paranoid_verify:
|
11
|
+
code_required: "Por favor ingrese el código provisto por nuestro equipo de soporte"
|
12
|
+
password_expired:
|
13
|
+
updated: "Su nueva contraña ha sido guardada."
|
14
|
+
change_required: "Su contraña ha expirado. Por favor renueve su contraseña."
|
15
|
+
failure:
|
16
|
+
session_limited: 'Sus credenciales de inicio de sesión fueron usadas en otro navegador. Por favor inicie sesión nuevamente para continuar en éste navegador.'
|
17
|
+
expired: 'Su cuenta ha expirado debido a inactividad. Por favor contacte al administrador de la aplicación.'
|
@@ -0,0 +1,10 @@
|
|
1
|
+
it:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
taken_in_past: "e' stata gia' utilizzata in passato!"
|
5
|
+
equal_to_current_password: " deve essere differente dalla password corrente!"
|
6
|
+
devise:
|
7
|
+
invalid_captcha: "Il captcha inserito non e' valido!"
|
8
|
+
password_expired:
|
9
|
+
updated: "La tua nuova password e' stata salvata."
|
10
|
+
change_required: "La tua password e' scaduta. Si prega di rinnovarla!"
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
|
3
|
+
require 'devise-security/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'devise-security'
|
7
|
+
s.version = DeviseSecurity::VERSION.dup
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.licenses = ['MIT']
|
10
|
+
s.summary = 'Security extension for devise'
|
11
|
+
s.email = 'natebird@gmail.com'
|
12
|
+
s.homepage = 'https://github.com/devise-security/devise-security'
|
13
|
+
s.description = 'An enterprise security extension for devise, trying to meet industrial standard security demands for web applications.'
|
14
|
+
s.authors = ['Marco Scholl', 'Alexander Dreher', 'Nate Bird']
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- test/*`.split("\n")
|
18
|
+
s.require_paths = ['lib']
|
19
|
+
s.required_ruby_version = '>= 2.1.0'
|
20
|
+
|
21
|
+
if RUBY_VERSION >= '2.4'
|
22
|
+
s.add_runtime_dependency 'rails', '>= 4.2.8', '< 6.0'
|
23
|
+
else
|
24
|
+
s.add_runtime_dependency 'railties', '>= 3.2.6', '< 6.0'
|
25
|
+
end
|
26
|
+
s.add_runtime_dependency 'devise', '>= 3.0.0', '< 5.0'
|
27
|
+
s.add_development_dependency 'bundler', '>= 1.3.0', '< 2.0'
|
28
|
+
s.add_development_dependency 'sqlite3', '~> 1.3', '>= 1.3.10'
|
29
|
+
s.add_development_dependency 'rubocop', '~> 0'
|
30
|
+
s.add_development_dependency 'minitest', '~> 5.0'
|
31
|
+
s.add_development_dependency 'easy_captcha', '~> 0'
|
32
|
+
s.add_development_dependency 'rails_email_validator', '~> 0'
|
33
|
+
s.add_development_dependency 'coveralls', '~> 0.8'
|
34
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'active_support/core_ext/integer'
|
3
|
+
require 'active_support/ordered_hash'
|
4
|
+
require 'active_support/concern'
|
5
|
+
require 'devise'
|
6
|
+
|
7
|
+
module Devise
|
8
|
+
|
9
|
+
# Should the password expire (e.g 3.months)
|
10
|
+
mattr_accessor :expire_password_after
|
11
|
+
@@expire_password_after = 3.months
|
12
|
+
|
13
|
+
# Validate password for strongness
|
14
|
+
mattr_accessor :password_regex
|
15
|
+
@@password_regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/
|
16
|
+
|
17
|
+
# Number of old passwords in archive
|
18
|
+
mattr_accessor :password_archiving_count
|
19
|
+
@@password_archiving_count = 5
|
20
|
+
|
21
|
+
# Deny old password (true, false, count)
|
22
|
+
mattr_accessor :deny_old_passwords
|
23
|
+
@@deny_old_passwords = true
|
24
|
+
|
25
|
+
# enable email validation for :secure_validatable. (true, false, validation_options)
|
26
|
+
# dependency: need an email validator like rails_email_validator
|
27
|
+
mattr_accessor :email_validation
|
28
|
+
@@email_validation = true
|
29
|
+
|
30
|
+
# captcha integration for recover form
|
31
|
+
mattr_accessor :captcha_for_recover
|
32
|
+
@@captcha_for_recover = false
|
33
|
+
|
34
|
+
# captcha integration for sign up form
|
35
|
+
mattr_accessor :captcha_for_sign_up
|
36
|
+
@@captcha_for_sign_up = false
|
37
|
+
|
38
|
+
# captcha integration for sign in form
|
39
|
+
mattr_accessor :captcha_for_sign_in
|
40
|
+
@@captcha_for_sign_in = false
|
41
|
+
|
42
|
+
# captcha integration for unlock form
|
43
|
+
mattr_accessor :captcha_for_unlock
|
44
|
+
@@captcha_for_unlock = false
|
45
|
+
|
46
|
+
# security_question integration for recover form
|
47
|
+
# this automatically enables captchas (captcha_for_recover, as fallback)
|
48
|
+
mattr_accessor :security_question_for_recover
|
49
|
+
@@security_question_for_recover = false
|
50
|
+
|
51
|
+
# security_question integration for unlock form
|
52
|
+
# this automatically enables captchas (captcha_for_unlock, as fallback)
|
53
|
+
mattr_accessor :security_question_for_unlock
|
54
|
+
@@security_question_for_unlock = false
|
55
|
+
|
56
|
+
# security_question integration for confirmation form
|
57
|
+
# this automatically enables captchas (captcha_for_confirmation, as fallback)
|
58
|
+
mattr_accessor :security_question_for_confirmation
|
59
|
+
@@security_question_for_confirmation = false
|
60
|
+
|
61
|
+
# captcha integration for confirmation form
|
62
|
+
mattr_accessor :captcha_for_confirmation
|
63
|
+
@@captcha_for_confirmation = false
|
64
|
+
|
65
|
+
# captcha integration for confirmation form
|
66
|
+
mattr_accessor :verification_code_generator
|
67
|
+
@@verification_code_generator = -> { SecureRandom.hex[0..4] }
|
68
|
+
|
69
|
+
# Time period for account expiry from last_activity_at
|
70
|
+
mattr_accessor :expire_after
|
71
|
+
@@expire_after = 90.days
|
72
|
+
mattr_accessor :delete_expired_after
|
73
|
+
@@delete_expired_after = 90.days
|
74
|
+
|
75
|
+
# paranoid_verification will regenerate verifacation code after faild attempt
|
76
|
+
mattr_accessor :paranoid_code_regenerate_after_attempt
|
77
|
+
@@paranoid_code_regenerate_after_attempt = 10
|
78
|
+
end
|
79
|
+
|
80
|
+
# an security extension for devise
|
81
|
+
module DeviseSecurity
|
82
|
+
autoload :Schema, 'devise-security/schema'
|
83
|
+
autoload :Patches, 'devise-security/patches'
|
84
|
+
|
85
|
+
module Controllers
|
86
|
+
autoload :Helpers, 'devise-security/controllers/helpers'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# modules
|
91
|
+
Devise.add_module :password_expirable, controller: :password_expirable, model: 'devise-security/models/password_expirable', route: :password_expired
|
92
|
+
Devise.add_module :secure_validatable, model: 'devise-security/models/secure_validatable'
|
93
|
+
Devise.add_module :password_archivable, model: 'devise-security/models/password_archivable'
|
94
|
+
Devise.add_module :session_limitable, model: 'devise-security/models/session_limitable'
|
95
|
+
Devise.add_module :session_non_transferable, model: 'devise-security/models/session_non_transferable'
|
96
|
+
Devise.add_module :expirable, model: 'devise-security/models/expirable'
|
97
|
+
Devise.add_module :security_questionable, model: 'devise-security/models/security_questionable'
|
98
|
+
Devise.add_module :paranoid_verification, controller: :paranoid_verification_code, model: 'devise-security/models/paranoid_verification', route: :verification_code
|
99
|
+
|
100
|
+
# requires
|
101
|
+
require 'devise-security/routes'
|
102
|
+
require 'devise-security/rails'
|
103
|
+
require 'devise-security/orm/active_record'
|
104
|
+
require 'devise-security/models/old_password'
|
105
|
+
require 'devise-security/models/database_authenticatable_patch'
|
106
|
+
require 'devise-security/models/paranoid_verification'
|
@@ -0,0 +1,96 @@
|
|
1
|
+
module DeviseSecurity
|
2
|
+
module Controllers
|
3
|
+
module Helpers
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
before_action :handle_password_change
|
8
|
+
before_action :handle_paranoid_verification
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
# helper for captcha
|
13
|
+
def init_recover_password_captcha
|
14
|
+
include RecoverPasswordCaptcha
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module RecoverPasswordCaptcha
|
19
|
+
def new
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# controller instance methods
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
# lookup if an password change needed
|
29
|
+
def handle_password_change
|
30
|
+
return if warden.nil?
|
31
|
+
|
32
|
+
if not devise_controller? and not ignore_password_expire? and not request.format.nil? and request.format.html?
|
33
|
+
Devise.mappings.keys.flatten.any? do |scope|
|
34
|
+
if signed_in?(scope) and warden.session(scope)['password_expired']
|
35
|
+
# re-check to avoid infinite loop if date changed after login attempt
|
36
|
+
if send(:"current_#{scope}").try(:need_change_password?)
|
37
|
+
store_location_for(scope, request.original_fullpath) if request.get?
|
38
|
+
redirect_for_password_change scope
|
39
|
+
return
|
40
|
+
else
|
41
|
+
warden.session(scope)[:password_expired] = false
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# lookup if extra (paranoid) code verification is needed
|
49
|
+
def handle_paranoid_verification
|
50
|
+
return if warden.nil?
|
51
|
+
|
52
|
+
if !devise_controller? && !request.format.nil? && request.format.html?
|
53
|
+
Devise.mappings.keys.flatten.any? do |scope|
|
54
|
+
if signed_in?(scope) && warden.session(scope)['paranoid_verify']
|
55
|
+
store_location_for(scope, request.original_fullpath) if request.get?
|
56
|
+
redirect_for_paranoid_verification scope
|
57
|
+
return
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# redirect for password update with alert message
|
64
|
+
def redirect_for_password_change(scope)
|
65
|
+
redirect_to change_password_required_path_for(scope), :alert => I18n.t('change_required', {:scope => 'devise.password_expired'})
|
66
|
+
end
|
67
|
+
|
68
|
+
def redirect_for_paranoid_verification(scope)
|
69
|
+
redirect_to paranoid_verification_code_path_for(scope), :alert => I18n.t('code_required', {:scope => 'devise.paranoid_verify'})
|
70
|
+
end
|
71
|
+
|
72
|
+
# path for change password
|
73
|
+
def change_password_required_path_for(resource_or_scope = nil)
|
74
|
+
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
75
|
+
change_path = "#{scope}_password_expired_path"
|
76
|
+
send(change_path)
|
77
|
+
end
|
78
|
+
|
79
|
+
def paranoid_verification_code_path_for(resource_or_scope = nil)
|
80
|
+
scope = Devise::Mapping.find_scope!(resource_or_scope)
|
81
|
+
change_path = "#{scope}_paranoid_verification_code_path"
|
82
|
+
send(change_path)
|
83
|
+
end
|
84
|
+
|
85
|
+
protected
|
86
|
+
|
87
|
+
# allow to overwrite for some special handlings
|
88
|
+
def ignore_password_expire?
|
89
|
+
false
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|