devise_security_extension 0.9.2 → 0.10.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +39 -0
  3. data/.rubocop.yml +38 -0
  4. data/Gemfile +1 -5
  5. data/Gemfile.lock +144 -141
  6. data/README.md +37 -11
  7. data/Rakefile +13 -29
  8. data/app/controllers/devise/paranoid_verification_code_controller.rb +42 -0
  9. data/app/controllers/devise/password_expired_controller.rb +16 -7
  10. data/app/views/devise/paranoid_verification_code/show.html.erb +10 -0
  11. data/config/locales/de.yml +2 -0
  12. data/config/locales/en.yml +6 -4
  13. data/config/locales/it.yml +10 -0
  14. data/devise_security_extension.gemspec +24 -104
  15. data/lib/devise_security_extension.rb +18 -8
  16. data/lib/devise_security_extension/controllers/helpers.rb +39 -6
  17. data/lib/devise_security_extension/hooks/paranoid_verification.rb +5 -0
  18. data/lib/devise_security_extension/hooks/session_limitable.rb +1 -0
  19. data/lib/devise_security_extension/models/paranoid_verification.rb +35 -0
  20. data/lib/devise_security_extension/models/password_archivable.rb +3 -7
  21. data/lib/devise_security_extension/models/password_expirable.rb +9 -5
  22. data/lib/devise_security_extension/patches/confirmations_controller_captcha.rb +3 -1
  23. data/lib/devise_security_extension/patches/confirmations_controller_security_question.rb +3 -1
  24. data/lib/devise_security_extension/patches/passwords_controller_captcha.rb +3 -1
  25. data/lib/devise_security_extension/patches/passwords_controller_security_question.rb +3 -1
  26. data/lib/devise_security_extension/patches/registrations_controller_captcha.rb +5 -3
  27. data/lib/devise_security_extension/patches/sessions_controller_captcha.rb +5 -3
  28. data/lib/devise_security_extension/patches/unlocks_controller_captcha.rb +3 -1
  29. data/lib/devise_security_extension/patches/unlocks_controller_security_question.rb +3 -1
  30. data/lib/devise_security_extension/routes.rb +4 -0
  31. data/lib/devise_security_extension/version.rb +3 -0
  32. data/lib/generators/devise_security_extension/install_generator.rb +16 -33
  33. data/lib/generators/templates/devise_security_extension.rb +38 -0
  34. data/test/dummy/Rakefile +6 -0
  35. data/test/dummy/app/controllers/application_controller.rb +2 -0
  36. data/test/dummy/app/controllers/foos_controller.rb +0 -0
  37. data/test/dummy/app/models/user.rb +2 -1
  38. data/test/dummy/app/views/foos/index.html.erb +0 -0
  39. data/test/dummy/config/application.rb +4 -2
  40. data/test/dummy/config/boot.rb +1 -1
  41. data/test/dummy/config/environments/test.rb +4 -2
  42. data/test/dummy/config/initializers/devise.rb +4 -4
  43. data/test/dummy/config/routes.rb +6 -0
  44. data/test/dummy/config/secrets.yml +3 -0
  45. data/test/dummy/db/migrate/20120508165529_create_tables.rb +4 -4
  46. data/test/dummy/db/migrate/20150402165590_add_verification_columns.rb +11 -0
  47. data/test/dummy/db/migrate/20150407162345_add_verification_attempt_column.rb +9 -0
  48. data/test/test_helper.rb +10 -0
  49. data/test/test_install_generator.rb +16 -0
  50. data/test/test_paranoid_verification.rb +124 -0
  51. data/test/test_password_archivable.rb +35 -21
  52. data/test/test_password_expired_controller.rb +24 -0
  53. metadata +104 -34
  54. data/VERSION +0 -1
  55. data/lib/devise_security_extension/models/security_question.rb +0 -3
  56. data/test/helper.rb +0 -22
  57. data/test/test_devise_security_extension.rb +0 -6
data/Rakefile CHANGED
@@ -1,39 +1,23 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
1
2
  require 'rubygems'
2
3
  require 'bundler'
3
- begin
4
- Bundler.setup(:default, :development)
5
- rescue Bundler::BundlerError => e
6
- $stderr.puts e.message
7
- $stderr.puts "Run `bundle install` to install missing gems"
8
- exit e.status_code
9
- end
10
- require 'rake'
4
+ require 'rake/testtask'
5
+ require 'rdoc/task'
6
+ require 'devise_security_extension/version'
11
7
 
12
- require 'jeweler'
13
- Jeweler::Tasks.new do |gem|
14
- # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
- gem.name = "devise_security_extension"
16
- gem.homepage = "http://github.com/phatworx/devise_security_extension"
17
- gem.license = "MIT"
18
- gem.summary = %Q{Security extension for devise}
19
- gem.description = %Q{An enterprise security extension for devise, trying to meet industrial standard security demands for web applications.}
20
- gem.email = "team@phatworx.de"
21
- gem.authors = ["Marco Scholl", "Alexander Dreher"]
22
- end
23
- Jeweler::RubygemsDotOrgTasks.new
8
+ desc 'Default: Run DeviseSecurityExtension unit tests'
9
+ task default: :test
24
10
 
25
- require 'rake/testtask'
26
- Rake::TestTask.new(:test) do |test|
27
- test.libs << 'lib' << 'test'
28
- test.pattern = 'test/**/test_*.rb'
29
- test.verbose = true
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
30
17
  end
31
18
 
32
- task :default => :test
33
-
34
- require 'rdoc/task'
35
19
  Rake::RDocTask.new do |rdoc|
36
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
20
+ version = DeviseSecurityExtension::VERSION.dup
37
21
 
38
22
  rdoc.rdoc_dir = 'rdoc'
39
23
  rdoc.title = "devise_security_extension #{version}"
@@ -0,0 +1,42 @@
1
+ class Devise::ParanoidVerificationCodeController < DeviseController
2
+ skip_before_filter :handle_paranoid_verification
3
+ prepend_before_filter :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
+ sign_in scope, resource, :bypass => true
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
@@ -1,13 +1,10 @@
1
1
  class Devise::PasswordExpiredController < DeviseController
2
2
  skip_before_filter :handle_password_change
3
+ before_filter :skip_password_change, only: [:show, :update]
3
4
  prepend_before_filter :authenticate_scope!, :only => [:show, :update]
4
5
 
5
6
  def show
6
- if not resource.nil? and resource.need_change_password?
7
- respond_with(resource)
8
- else
9
- redirect_to :root
10
- end
7
+ respond_with(resource)
11
8
  end
12
9
 
13
10
  def update
@@ -24,9 +21,21 @@ class Devise::PasswordExpiredController < DeviseController
24
21
  end
25
22
 
26
23
  private
27
- def resource_params
28
- params.require(resource_name).permit(:current_password, :password, :password_confirmation)
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)
29
37
  end
38
+ end
30
39
 
31
40
  def scope
32
41
  resource_name.to_sym
@@ -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 %>
@@ -6,6 +6,8 @@ de:
6
6
  password_format: "müssen große, kleine Buchstaben und Ziffern enthalten"
7
7
  devise:
8
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"
9
11
  password_expired:
10
12
  updated: "Das neue Passwort wurde übernommen."
11
13
  change_required: "Ihr Passwort ist abgelaufen. Bitte vergeben sie ein neues Passwort!"
@@ -1,14 +1,16 @@
1
1
  en:
2
2
  errors:
3
3
  messages:
4
- taken_in_past: "was already taken in the past!"
5
- equal_to_current_password: "must be different to the current password!"
4
+ taken_in_past: "was used previously."
5
+ equal_to_current_password: "must be different than the current password."
6
6
  password_format: "must contain big, small letters and digits"
7
7
  devise:
8
- invalid_captcha: "The captcha input is not valid!"
8
+ invalid_captcha: "The captcha input was invalid."
9
+ paranoid_verify:
10
+ code_required: "Please enter the code our support team provided"
9
11
  password_expired:
10
12
  updated: "Your new password is saved."
11
- change_required: "Your password is expired. Please renew your password!"
13
+ change_required: "Your password is expired. Please renew your password."
12
14
  failure:
13
15
  session_limited: 'Your login credentials were used in another browser. Please sign in again to continue in this browser.'
14
16
  expired: 'Your account has expired due to inactivity. Please contact the site administrator.'
@@ -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!"
@@ -1,111 +1,31 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
1
  # -*- encoding: utf-8 -*-
5
- # stub: devise_security_extension 0.8.3 ruby lib
2
+ $LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
3
+ require 'devise_security_extension/version'
6
4
 
7
5
  Gem::Specification.new do |s|
8
- s.name = "devise_security_extension"
9
- s.version = "0.9.2"
6
+ s.name = 'devise_security_extension'
7
+ s.version = DeviseSecurityExtension::VERSION.dup
8
+ s.platform = Gem::Platform::RUBY
9
+ s.licenses = ['MIT']
10
+ s.summary = 'Security extension for devise'
11
+ s.email = 'team@phatworx.de'
12
+ s.homepage = 'https://github.com/phatworx/devise_security_extension'
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']
10
15
 
11
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
- s.require_paths = ["lib"]
13
- s.authors = ["Marco Scholl", "Alexander Dreher"]
14
- s.date = "2015-04-02"
15
- s.description = "An enterprise security extension for devise, trying to meet industrial standard security demands for web applications."
16
- s.email = "team@phatworx.de"
17
- s.extra_rdoc_files = [
18
- "LICENSE.txt",
19
- "README.md"
20
- ]
21
- s.files = [
22
- ".document",
23
- "Gemfile",
24
- "Gemfile.lock",
25
- "LICENSE.txt",
26
- "README.md",
27
- "Rakefile",
28
- "VERSION",
29
- "app/controllers/devise/password_expired_controller.rb",
30
- "app/views/devise/password_expired/show.html.erb",
31
- "config/locales/de.yml",
32
- "config/locales/en.yml",
33
- "devise_security_extension.gemspec",
34
- "lib/devise_security_extension.rb",
35
- "lib/devise_security_extension/controllers/helpers.rb",
36
- "lib/devise_security_extension/hooks/expirable.rb",
37
- "lib/devise_security_extension/hooks/password_expirable.rb",
38
- "lib/devise_security_extension/hooks/session_limitable.rb",
39
- "lib/devise_security_extension/models/expirable.rb",
40
- "lib/devise_security_extension/models/old_password.rb",
41
- "lib/devise_security_extension/models/password_archivable.rb",
42
- "lib/devise_security_extension/models/password_expirable.rb",
43
- "lib/devise_security_extension/models/secure_validatable.rb",
44
- "lib/devise_security_extension/models/security_question.rb",
45
- "lib/devise_security_extension/models/security_questionable.rb",
46
- "lib/devise_security_extension/models/session_limitable.rb",
47
- "lib/devise_security_extension/orm/active_record.rb",
48
- "lib/devise_security_extension/models/database_authenticatable_patch.rb",
49
- "lib/devise_security_extension/patches.rb",
50
- "lib/devise_security_extension/patches/confirmations_controller_captcha.rb",
51
- "lib/devise_security_extension/patches/confirmations_controller_security_question.rb",
52
- "lib/devise_security_extension/patches/passwords_controller_captcha.rb",
53
- "lib/devise_security_extension/patches/passwords_controller_security_question.rb",
54
- "lib/devise_security_extension/patches/registrations_controller_captcha.rb",
55
- "lib/devise_security_extension/patches/sessions_controller_captcha.rb",
56
- "lib/devise_security_extension/patches/unlocks_controller_captcha.rb",
57
- "lib/devise_security_extension/patches/unlocks_controller_security_question.rb",
58
- "lib/devise_security_extension/rails.rb",
59
- "lib/devise_security_extension/routes.rb",
60
- "lib/devise_security_extension/schema.rb",
61
- "lib/generators/devise_security_extension/install_generator.rb",
62
- "test/dummy/app/models/.gitkeep",
63
- "test/dummy/app/models/user.rb",
64
- "test/dummy/config.ru",
65
- "test/dummy/config/application.rb",
66
- "test/dummy/config/boot.rb",
67
- "test/dummy/config/database.yml",
68
- "test/dummy/config/environment.rb",
69
- "test/dummy/config/environments/test.rb",
70
- "test/dummy/config/initializers/devise.rb",
71
- "test/dummy/db/migrate/20120508165529_create_tables.rb",
72
- "test/helper.rb",
73
- "test/test_devise_security_extension.rb",
74
- "test/test_password_archivable.rb"
75
- ]
76
- s.homepage = "http://github.com/phatworx/devise_security_extension"
77
- s.licenses = ["MIT"]
78
- s.rubygems_version = "2.2.2"
79
- s.summary = "Security extension for devise"
16
+ s.rubyforge_project = 'devise_security_extension'
80
17
 
81
- if s.respond_to? :specification_version then
82
- s.specification_version = 4
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- test/*`.split("\n")
20
+ s.require_paths = ['lib']
21
+ s.required_ruby_version = '>= 1.9.3'
83
22
 
84
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
85
- s.add_runtime_dependency(%q<rails>, [">= 3.1.1"])
86
- s.add_runtime_dependency(%q<devise>, [">= 2.0.0"])
87
- s.add_development_dependency(%q<rails_email_validator>, [">= 0"])
88
- s.add_development_dependency(%q<easy_captcha>, [">= 0"])
89
- s.add_development_dependency(%q<bundler>, [">= 1.0.0"])
90
- s.add_development_dependency(%q<jeweler>, ["~> 2.0.1"])
91
- s.add_development_dependency(%q<sqlite3>, [">= 0"])
92
- else
93
- s.add_dependency(%q<rails>, [">= 3.1.1"])
94
- s.add_dependency(%q<devise>, [">= 2.0.0"])
95
- s.add_dependency(%q<rails_email_validator>, [">= 0"])
96
- s.add_dependency(%q<easy_captcha>, [">= 0"])
97
- s.add_dependency(%q<bundler>, [">= 1.0.0"])
98
- s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
99
- s.add_dependency(%q<sqlite3>, [">= 0"])
100
- end
101
- else
102
- s.add_dependency(%q<rails>, [">= 3.1.1"])
103
- s.add_dependency(%q<devise>, [">= 2.0.0"])
104
- s.add_dependency(%q<rails_email_validator>, [">= 0"])
105
- s.add_dependency(%q<easy_captcha>, [">= 0"])
106
- s.add_dependency(%q<bundler>, [">= 1.0.0"])
107
- s.add_dependency(%q<jeweler>, ["~> 2.0.1"])
108
- s.add_dependency(%q<sqlite3>, [">= 0"])
109
- end
23
+ s.add_runtime_dependency 'railties', '>= 3.2.6', '< 5.0'
24
+ s.add_runtime_dependency 'devise', '>= 3.0.0', '< 4.0'
25
+ s.add_development_dependency 'bundler', '>= 1.3.0', '< 2.0'
26
+ s.add_development_dependency 'sqlite3', '~> 1.3.10'
27
+ s.add_development_dependency 'rubocop', '~> 0'
28
+ s.add_development_dependency 'minitest'
29
+ s.add_development_dependency 'easy_captcha', '~> 0'
30
+ s.add_development_dependency 'rails_email_validator', '~> 0'
110
31
  end
111
-
@@ -14,7 +14,7 @@ module Devise
14
14
  mattr_accessor :password_regex
15
15
  @@password_regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/
16
16
 
17
- # How often save old passwords in archive
17
+ # Number of old passwords in archive
18
18
  mattr_accessor :password_archiving_count
19
19
  @@password_archiving_count = 5
20
20
 
@@ -62,11 +62,19 @@ module Devise
62
62
  mattr_accessor :captcha_for_confirmation
63
63
  @@captcha_for_confirmation = false
64
64
 
65
+ # captcha integration for confirmation form
66
+ mattr_accessor :verification_code_generator
67
+ @@verification_code_generator = -> { SecureRandom.hex[0..4] }
68
+
65
69
  # Time period for account expiry from last_activity_at
66
70
  mattr_accessor :expire_after
67
71
  @@expire_after = 90.days
68
72
  mattr_accessor :delete_expired_after
69
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
70
78
  end
71
79
 
72
80
  # an security extension for devise
@@ -80,17 +88,19 @@ module DeviseSecurityExtension
80
88
  end
81
89
 
82
90
  # modules
83
- Devise.add_module :password_expirable, :controller => :password_expirable, :model => 'devise_security_extension/models/password_expirable', :route => :password_expired
84
- Devise.add_module :secure_validatable, :model => 'devise_security_extension/models/secure_validatable'
85
- Devise.add_module :password_archivable, :model => 'devise_security_extension/models/password_archivable'
86
- Devise.add_module :session_limitable, :model => 'devise_security_extension/models/session_limitable'
87
- Devise.add_module :expirable, :model => 'devise_security_extension/models/expirable'
88
- Devise.add_module :security_questionable, :model => 'devise_security_extension/models/security_questionable'
91
+ Devise.add_module :password_expirable, controller: :password_expirable, model: 'devise_security_extension/models/password_expirable', route: :password_expired
92
+ Devise.add_module :secure_validatable, model: 'devise_security_extension/models/secure_validatable'
93
+ Devise.add_module :password_archivable, model: 'devise_security_extension/models/password_archivable'
94
+ Devise.add_module :session_limitable, model: 'devise_security_extension/models/session_limitable'
95
+ Devise.add_module :session_non_transferable, model: 'devise_security_extension/models/session_non_transferable'
96
+ Devise.add_module :expirable, model: 'devise_security_extension/models/expirable'
97
+ Devise.add_module :security_questionable, model: 'devise_security_extension/models/security_questionable'
98
+ Devise.add_module :paranoid_verification, controller: :paranoid_verification_code, model: 'devise_security_extension/models/paranoid_verification', route: :verification_code
89
99
 
90
100
  # requires
91
101
  require 'devise_security_extension/routes'
92
102
  require 'devise_security_extension/rails'
93
103
  require 'devise_security_extension/orm/active_record'
94
104
  require 'devise_security_extension/models/old_password'
95
- require 'devise_security_extension/models/security_question'
96
105
  require 'devise_security_extension/models/database_authenticatable_patch'
106
+ require 'devise_security_extension/models/paranoid_verification'
@@ -5,13 +5,14 @@ module DeviseSecurityExtension
5
5
 
6
6
  included do
7
7
  before_filter :handle_password_change
8
+ before_filter :handle_paranoid_verification
8
9
  end
9
-
10
+
10
11
  module ClassMethods
11
12
  # helper for captcha
12
13
  def init_recover_password_captcha
13
14
  include RecoverPasswordCaptcha
14
- end
15
+ end
15
16
  end
16
17
 
17
18
  module RecoverPasswordCaptcha
@@ -26,11 +27,33 @@ module DeviseSecurityExtension
26
27
 
27
28
  # lookup if an password change needed
28
29
  def handle_password_change
30
+ return if warden.nil?
31
+
29
32
  if not devise_controller? and not ignore_password_expire? and not request.format.nil? and request.format.html?
30
33
  Devise.mappings.keys.flatten.any? do |scope|
31
34
  if signed_in?(scope) and warden.session(scope)['password_expired']
32
- session["#{scope}_return_to"] = request.path if request.get?
33
- redirect_for_password_change scope
35
+ # re-check to avoid infinite loop if date changed after login attempt
36
+ if send(:"current_#{scope}").try(:need_change_password?)
37
+ session["#{scope}_return_to"] = 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
+ session["#{scope}_return_to"] = request.original_fullpath if request.get?
56
+ redirect_for_paranoid_verification scope
34
57
  return
35
58
  end
36
59
  end
@@ -42,15 +65,25 @@ module DeviseSecurityExtension
42
65
  redirect_to change_password_required_path_for(scope), :alert => I18n.t('change_required', {:scope => 'devise.password_expired'})
43
66
  end
44
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
+
45
72
  # path for change password
46
73
  def change_password_required_path_for(resource_or_scope = nil)
47
74
  scope = Devise::Mapping.find_scope!(resource_or_scope)
48
75
  change_path = "#{scope}_password_expired_path"
49
76
  send(change_path)
50
77
  end
51
-
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
+
52
85
  protected
53
-
86
+
54
87
  # allow to overwrite for some special handlings
55
88
  def ignore_password_expire?
56
89
  false