devise_security_extension 0.6.0 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Gemfile.lock +68 -44
- data/README.rdoc +17 -14
- data/VERSION +1 -1
- data/app/controllers/devise/password_expired_controller.rb +4 -4
- data/devise_security_extension.gemspec +11 -7
- data/lib/devise_security_extension.rb +5 -1
- data/lib/devise_security_extension/controllers/helpers.rb +4 -8
- data/lib/devise_security_extension/models/expirable.rb +38 -41
- data/lib/devise_security_extension/models/old_password.rb +3 -1
- data/lib/devise_security_extension/models/password_archivable.rb +39 -46
- data/lib/devise_security_extension/models/password_expirable.rb +29 -35
- data/lib/devise_security_extension/models/secure_validatable.rb +3 -1
- data/lib/devise_security_extension/models/session_limitable.rb +2 -2
- data/lib/devise_security_extension/patches.rb +10 -5
- data/lib/devise_security_extension/patches/confirmations_controller_captcha.rb +21 -0
- data/lib/devise_security_extension/patches/passwords_controller_captcha.rb +20 -0
- data/lib/devise_security_extension/patches/registrations_controller_captcha.rb +33 -0
- data/lib/devise_security_extension/patches/sessions_controller_captcha.rb +23 -0
- data/lib/devise_security_extension/patches/unlocks_controller_captcha.rb +20 -0
- data/lib/devise_security_extension/rails.rb +1 -1
- data/lib/devise_security_extension/routes.rb +2 -2
- data/lib/generators/devise_security_extension/install_generator.rb +4 -3
- metadata +52 -18
- data/lib/devise_security_extension/patches/controller_captcha.rb +0 -21
data/Gemfile
CHANGED
@@ -2,7 +2,7 @@ source "http://rubygems.org"
|
|
2
2
|
# Add dependencies required to use your gem here.
|
3
3
|
# Example:
|
4
4
|
gem "rails", ">= 3.1.1"
|
5
|
-
gem "devise"
|
5
|
+
gem "devise", ">= 2.0.0"
|
6
6
|
|
7
7
|
# Add dependencies to develop your gem here.
|
8
8
|
# Include everything needed to run rake, tests, features, etc.
|
data/Gemfile.lock
CHANGED
@@ -1,43 +1,49 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
actionmailer (3.1
|
5
|
-
actionpack (= 3.1
|
6
|
-
mail (~> 2.
|
7
|
-
actionpack (3.1
|
8
|
-
activemodel (= 3.1
|
9
|
-
activesupport (= 3.1
|
4
|
+
actionmailer (3.2.1)
|
5
|
+
actionpack (= 3.2.1)
|
6
|
+
mail (~> 2.4.0)
|
7
|
+
actionpack (3.2.1)
|
8
|
+
activemodel (= 3.2.1)
|
9
|
+
activesupport (= 3.2.1)
|
10
10
|
builder (~> 3.0.0)
|
11
11
|
erubis (~> 2.7.0)
|
12
|
-
|
13
|
-
rack (~> 1.
|
12
|
+
journey (~> 1.0.1)
|
13
|
+
rack (~> 1.4.0)
|
14
14
|
rack-cache (~> 1.1)
|
15
|
-
rack-mount (~> 0.8.2)
|
16
15
|
rack-test (~> 0.6.1)
|
17
|
-
sprockets (~> 2.
|
18
|
-
activemodel (3.1
|
19
|
-
activesupport (= 3.1
|
16
|
+
sprockets (~> 2.1.2)
|
17
|
+
activemodel (3.2.1)
|
18
|
+
activesupport (= 3.2.1)
|
20
19
|
builder (~> 3.0.0)
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
arel (~> 2.2.1)
|
20
|
+
activerecord (3.2.1)
|
21
|
+
activemodel (= 3.2.1)
|
22
|
+
activesupport (= 3.2.1)
|
23
|
+
arel (~> 3.0.0)
|
26
24
|
tzinfo (~> 0.3.29)
|
27
|
-
activeresource (3.1
|
28
|
-
activemodel (= 3.1
|
29
|
-
activesupport (= 3.1
|
30
|
-
activesupport (3.1
|
25
|
+
activeresource (3.2.1)
|
26
|
+
activemodel (= 3.2.1)
|
27
|
+
activesupport (= 3.2.1)
|
28
|
+
activesupport (3.2.1)
|
29
|
+
i18n (~> 0.6)
|
31
30
|
multi_json (~> 1.0)
|
32
|
-
arel (
|
31
|
+
arel (3.0.0)
|
33
32
|
bcrypt-ruby (3.0.1)
|
34
33
|
builder (3.0.0)
|
35
|
-
devise (
|
34
|
+
devise (2.0.0)
|
36
35
|
bcrypt-ruby (~> 3.0)
|
37
36
|
orm_adapter (~> 0.0.3)
|
37
|
+
railties (~> 3.1)
|
38
38
|
warden (~> 1.1)
|
39
|
-
|
39
|
+
diff-lcs (1.1.3)
|
40
|
+
easy_captcha (0.4.7)
|
41
|
+
bundler (~> 1.0.0)
|
40
42
|
rails (>= 3.0.0)
|
43
|
+
rmagick (>= 2.13.1)
|
44
|
+
rspec-rails (~> 2.8.1)
|
45
|
+
simplecov (>= 0.3.8)
|
46
|
+
yard (>= 0.7.0)
|
41
47
|
erubis (2.7.0)
|
42
48
|
git (1.2.5)
|
43
49
|
hike (1.2.1)
|
@@ -46,45 +52,62 @@ GEM
|
|
46
52
|
bundler (~> 1.0.0)
|
47
53
|
git (>= 1.2.5)
|
48
54
|
rake
|
49
|
-
|
50
|
-
|
55
|
+
journey (1.0.1)
|
56
|
+
json (1.6.5)
|
57
|
+
mail (2.4.1)
|
51
58
|
i18n (>= 0.4.0)
|
52
59
|
mime-types (~> 1.16)
|
53
60
|
treetop (~> 1.4.8)
|
54
61
|
mime-types (1.17.2)
|
55
|
-
multi_json (1.0.
|
56
|
-
orm_adapter (0.0.
|
62
|
+
multi_json (1.0.4)
|
63
|
+
orm_adapter (0.0.6)
|
57
64
|
polyglot (0.3.3)
|
58
|
-
rack (1.
|
65
|
+
rack (1.4.1)
|
59
66
|
rack-cache (1.1)
|
60
67
|
rack (>= 0.4)
|
61
|
-
rack-mount (0.8.3)
|
62
|
-
rack (>= 1.0.0)
|
63
68
|
rack-ssl (1.3.2)
|
64
69
|
rack
|
65
70
|
rack-test (0.6.1)
|
66
71
|
rack (>= 1.0)
|
67
|
-
rails (3.1
|
68
|
-
actionmailer (= 3.1
|
69
|
-
actionpack (= 3.1
|
70
|
-
activerecord (= 3.1
|
71
|
-
activeresource (= 3.1
|
72
|
-
activesupport (= 3.1
|
72
|
+
rails (3.2.1)
|
73
|
+
actionmailer (= 3.2.1)
|
74
|
+
actionpack (= 3.2.1)
|
75
|
+
activerecord (= 3.2.1)
|
76
|
+
activeresource (= 3.2.1)
|
77
|
+
activesupport (= 3.2.1)
|
73
78
|
bundler (~> 1.0)
|
74
|
-
railties (= 3.1
|
79
|
+
railties (= 3.2.1)
|
75
80
|
rails_email_validator (0.1.4)
|
76
81
|
activemodel (>= 3.0.0)
|
77
|
-
railties (3.1
|
78
|
-
actionpack (= 3.1
|
79
|
-
activesupport (= 3.1
|
82
|
+
railties (3.2.1)
|
83
|
+
actionpack (= 3.2.1)
|
84
|
+
activesupport (= 3.2.1)
|
80
85
|
rack-ssl (~> 1.3.2)
|
81
86
|
rake (>= 0.8.7)
|
82
87
|
rdoc (~> 3.4)
|
83
88
|
thor (~> 0.14.6)
|
84
89
|
rake (0.9.2.2)
|
85
|
-
rdoc (3.
|
90
|
+
rdoc (3.12)
|
86
91
|
json (~> 1.4)
|
87
|
-
|
92
|
+
rmagick (2.13.1)
|
93
|
+
rspec (2.8.0)
|
94
|
+
rspec-core (~> 2.8.0)
|
95
|
+
rspec-expectations (~> 2.8.0)
|
96
|
+
rspec-mocks (~> 2.8.0)
|
97
|
+
rspec-core (2.8.0)
|
98
|
+
rspec-expectations (2.8.0)
|
99
|
+
diff-lcs (~> 1.1.2)
|
100
|
+
rspec-mocks (2.8.0)
|
101
|
+
rspec-rails (2.8.1)
|
102
|
+
actionpack (>= 3.0)
|
103
|
+
activesupport (>= 3.0)
|
104
|
+
railties (>= 3.0)
|
105
|
+
rspec (~> 2.8.0)
|
106
|
+
simplecov (0.5.4)
|
107
|
+
multi_json (~> 1.0.3)
|
108
|
+
simplecov-html (~> 0.5.3)
|
109
|
+
simplecov-html (0.5.3)
|
110
|
+
sprockets (2.1.2)
|
88
111
|
hike (~> 1.2)
|
89
112
|
rack (~> 1.0)
|
90
113
|
tilt (~> 1.1, != 1.3.0)
|
@@ -96,13 +119,14 @@ GEM
|
|
96
119
|
tzinfo (0.3.31)
|
97
120
|
warden (1.1.0)
|
98
121
|
rack (>= 1.0)
|
122
|
+
yard (0.7.5)
|
99
123
|
|
100
124
|
PLATFORMS
|
101
125
|
ruby
|
102
126
|
|
103
127
|
DEPENDENCIES
|
104
128
|
bundler (~> 1.0.0)
|
105
|
-
devise
|
129
|
+
devise (>= 2.0.0)
|
106
130
|
easy_captcha
|
107
131
|
jeweler (~> 1.5.2)
|
108
132
|
rails (>= 3.1.1)
|
data/README.rdoc
CHANGED
@@ -76,39 +76,41 @@ That's it!
|
|
76
76
|
=== Password expirable
|
77
77
|
|
78
78
|
create_table :the_resources do |t|
|
79
|
-
|
79
|
+
# other devise fields
|
80
|
+
|
81
|
+
t.datetime :password_changed_at
|
80
82
|
end
|
83
|
+
add_index :the_resources, :password_changed_at
|
81
84
|
|
82
85
|
=== Password archivable
|
83
86
|
|
84
87
|
create_table :old_passwords do |t|
|
85
|
-
t.
|
88
|
+
t.string :encrypted_password, :null => false
|
89
|
+
t.string :password_salt
|
90
|
+
t.string :password_archivable_type, :null => false
|
91
|
+
t.integer :password_archivable_id, :null => false
|
92
|
+
t.datetime :created_at
|
86
93
|
end
|
87
94
|
add_index :old_passwords, [:password_archivable_type, :password_archivable_id], :name => :index_password_archivable
|
88
95
|
|
89
96
|
=== Session limitable
|
90
97
|
|
91
98
|
create_table :the_resources do |t|
|
92
|
-
|
99
|
+
# other devise fields
|
100
|
+
|
101
|
+
t.string :unique_session_id, :limit => 20
|
93
102
|
end
|
94
103
|
|
95
104
|
=== Expirable
|
96
|
-
Devise 2.0 style migrations on new resource:
|
97
105
|
|
98
106
|
create_table :the_resources do |t|
|
99
|
-
|
100
|
-
t.datetime :last_activity_at
|
101
|
-
t.datetime :expired_at
|
102
|
-
...
|
103
|
-
end
|
107
|
+
# other devise fields
|
104
108
|
|
105
|
-
Add module to existing resource with
|
106
|
-
|
107
|
-
change_table :the_resources do |t|
|
108
109
|
t.datetime :last_activity_at
|
109
110
|
t.datetime :expired_at
|
110
111
|
end
|
111
|
-
|
112
|
+
add_index :the_resources, :last_activity_at
|
113
|
+
add_index :the_resources, :expired_at
|
112
114
|
|
113
115
|
== Requirements
|
114
116
|
|
@@ -133,6 +135,7 @@ Add module to existing resource with
|
|
133
135
|
* Team Phatworx (http://github.com/phatworx)
|
134
136
|
* Marco Scholl (http://github.com/traxanos)
|
135
137
|
* Alexander Dreher (http://github.com/alexdreher)
|
138
|
+
* Christoph Chilian (http://github.com/cc-web)
|
136
139
|
|
137
140
|
== Contributing to devise_security_extension
|
138
141
|
|
@@ -146,4 +149,4 @@ Add module to existing resource with
|
|
146
149
|
|
147
150
|
== Copyright
|
148
151
|
|
149
|
-
Copyright (c) 2011 Marco Scholl. See LICENSE.txt for further details.
|
152
|
+
Copyright (c) 2011-2012 Marco Scholl. See LICENSE.txt for further details.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.6.
|
1
|
+
0.6.1
|
@@ -1,11 +1,11 @@
|
|
1
|
-
class Devise::PasswordExpiredController <
|
1
|
+
class Devise::PasswordExpiredController < DeviseController
|
2
2
|
skip_before_filter :handle_password_change
|
3
3
|
prepend_before_filter :authenticate_scope!, :only => [:show, :update]
|
4
|
-
include Devise::Controllers::
|
4
|
+
include Devise::Controllers::Helpers
|
5
5
|
|
6
6
|
def show
|
7
7
|
if not resource.nil? and resource.need_change_password?
|
8
|
-
|
8
|
+
render 'devise/password_expired/show'
|
9
9
|
else
|
10
10
|
redirect_to :root
|
11
11
|
end
|
@@ -19,7 +19,7 @@ class Devise::PasswordExpiredController < ApplicationController
|
|
19
19
|
redirect_to stored_location_for(scope) || :root
|
20
20
|
else
|
21
21
|
clean_up_passwords(resource)
|
22
|
-
|
22
|
+
render 'devise/password_expired/show'
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "devise_security_extension"
|
8
|
-
s.version = "0.6.
|
8
|
+
s.version = "0.6.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Marco Scholl", "Alexander Dreher"]
|
12
|
-
s.date = "
|
12
|
+
s.date = "2012-06-06"
|
13
13
|
s.description = "An enterprise security extension for devise, trying to meet industrial standard security demands for web applications."
|
14
14
|
s.email = "team@phatworx.de"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -42,7 +42,11 @@ Gem::Specification.new do |s|
|
|
42
42
|
"lib/devise_security_extension/models/session_limitable.rb",
|
43
43
|
"lib/devise_security_extension/orm/active_record.rb",
|
44
44
|
"lib/devise_security_extension/patches.rb",
|
45
|
-
"lib/devise_security_extension/patches/
|
45
|
+
"lib/devise_security_extension/patches/confirmations_controller_captcha.rb",
|
46
|
+
"lib/devise_security_extension/patches/passwords_controller_captcha.rb",
|
47
|
+
"lib/devise_security_extension/patches/registrations_controller_captcha.rb",
|
48
|
+
"lib/devise_security_extension/patches/sessions_controller_captcha.rb",
|
49
|
+
"lib/devise_security_extension/patches/unlocks_controller_captcha.rb",
|
46
50
|
"lib/devise_security_extension/rails.rb",
|
47
51
|
"lib/devise_security_extension/routes.rb",
|
48
52
|
"lib/devise_security_extension/schema.rb",
|
@@ -53,7 +57,7 @@ Gem::Specification.new do |s|
|
|
53
57
|
s.homepage = "http://github.com/phatworx/devise_security_extension"
|
54
58
|
s.licenses = ["MIT"]
|
55
59
|
s.require_paths = ["lib"]
|
56
|
-
s.rubygems_version = "1.8.
|
60
|
+
s.rubygems_version = "1.8.21"
|
57
61
|
s.summary = "Security extension for devise"
|
58
62
|
s.test_files = [
|
59
63
|
"test/helper.rb",
|
@@ -65,14 +69,14 @@ Gem::Specification.new do |s|
|
|
65
69
|
|
66
70
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
67
71
|
s.add_runtime_dependency(%q<rails>, [">= 3.1.1"])
|
68
|
-
s.add_runtime_dependency(%q<devise>, [">= 0"])
|
72
|
+
s.add_runtime_dependency(%q<devise>, [">= 2.0.0"])
|
69
73
|
s.add_development_dependency(%q<rails_email_validator>, [">= 0"])
|
70
74
|
s.add_development_dependency(%q<easy_captcha>, [">= 0"])
|
71
75
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
72
76
|
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
73
77
|
else
|
74
78
|
s.add_dependency(%q<rails>, [">= 3.1.1"])
|
75
|
-
s.add_dependency(%q<devise>, [">= 0"])
|
79
|
+
s.add_dependency(%q<devise>, [">= 2.0.0"])
|
76
80
|
s.add_dependency(%q<rails_email_validator>, [">= 0"])
|
77
81
|
s.add_dependency(%q<easy_captcha>, [">= 0"])
|
78
82
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
@@ -80,7 +84,7 @@ Gem::Specification.new do |s|
|
|
80
84
|
end
|
81
85
|
else
|
82
86
|
s.add_dependency(%q<rails>, [">= 3.1.1"])
|
83
|
-
s.add_dependency(%q<devise>, [">= 0"])
|
87
|
+
s.add_dependency(%q<devise>, [">= 2.0.0"])
|
84
88
|
s.add_dependency(%q<rails_email_validator>, [">= 0"])
|
85
89
|
s.add_dependency(%q<easy_captcha>, [">= 0"])
|
86
90
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
@@ -5,7 +5,7 @@ require 'active_support/ordered_hash'
|
|
5
5
|
require 'active_support/concern'
|
6
6
|
require 'devise'
|
7
7
|
|
8
|
-
module Devise
|
8
|
+
module Devise
|
9
9
|
|
10
10
|
# Should the password expire (e.g 3.months)
|
11
11
|
mattr_accessor :expire_password_after
|
@@ -43,6 +43,10 @@ module Devise # :nodoc:
|
|
43
43
|
# captcha integration for unlock form
|
44
44
|
mattr_accessor :captcha_for_unlock
|
45
45
|
@@captcha_for_unlock = false
|
46
|
+
|
47
|
+
# captcha integration for confirmation form
|
48
|
+
mattr_accessor :captcha_for_confirmation
|
49
|
+
@@captcha_for_confirmation = false
|
46
50
|
|
47
51
|
# Time period for account expiry from last_activity_at
|
48
52
|
mattr_accessor :expire_after
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module DeviseSecurityExtension
|
2
|
-
module Controllers
|
3
|
-
module Helpers
|
2
|
+
module Controllers
|
3
|
+
module Helpers
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
@@ -10,22 +10,18 @@ module DeviseSecurityExtension
|
|
10
10
|
module ClassMethods
|
11
11
|
# helper for captcha
|
12
12
|
def init_recover_password_captcha
|
13
|
-
p "init"
|
14
|
-
p self.inspect
|
15
|
-
|
16
13
|
include RecoverPasswordCaptcha
|
17
14
|
end
|
18
15
|
end
|
19
16
|
|
20
17
|
module RecoverPasswordCaptcha
|
21
18
|
def new
|
22
|
-
p "Check here captcha"
|
23
19
|
super
|
24
20
|
end
|
25
21
|
end
|
26
22
|
|
27
23
|
# controller instance methods
|
28
|
-
|
24
|
+
|
29
25
|
private
|
30
26
|
|
31
27
|
# lookup if an password change needed
|
@@ -60,7 +56,7 @@ module DeviseSecurityExtension
|
|
60
56
|
false
|
61
57
|
end
|
62
58
|
|
63
|
-
|
59
|
+
|
64
60
|
end
|
65
61
|
end
|
66
62
|
|
@@ -18,51 +18,48 @@ module Devise
|
|
18
18
|
module Expirable
|
19
19
|
extend ActiveSupport::Concern
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
# Tells if the account has expired
|
29
|
-
#
|
30
|
-
# @return [bool]
|
31
|
-
def expired?
|
32
|
-
# expired_at set (manually, via cron, etc.)
|
33
|
-
return self.expired_at < Time.now.utc unless self.expired_at.nil?
|
34
|
-
# if it is not set, check the last activity against configured expire_after time range
|
35
|
-
return self.last_activity_at < self.class.expire_after.ago unless self.last_activity_at.nil?
|
36
|
-
# if last_activity_at is nil as well, the user has to be 'fresh' and is therefore not expired
|
37
|
-
false
|
38
|
-
end
|
21
|
+
# Updates +last_activity_at+, called from a Warden::Manager.after_set_user hook.
|
22
|
+
def update_last_activitiy!
|
23
|
+
self.last_activity_at = Time.now.utc
|
24
|
+
save(:validate => false)
|
25
|
+
end
|
39
26
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
#
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
27
|
+
# Tells if the account has expired
|
28
|
+
#
|
29
|
+
# @return [bool]
|
30
|
+
def expired?
|
31
|
+
# expired_at set (manually, via cron, etc.)
|
32
|
+
return self.expired_at < Time.now.utc unless self.expired_at.nil?
|
33
|
+
# if it is not set, check the last activity against configured expire_after time range
|
34
|
+
return self.last_activity_at < self.class.expire_after.ago unless self.last_activity_at.nil?
|
35
|
+
# if last_activity_at is nil as well, the user has to be 'fresh' and is therefore not expired
|
36
|
+
false
|
37
|
+
end
|
50
38
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
39
|
+
# Expire an account. This is for cron jobs and manually expiring of accounts.
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
# User.expire!
|
43
|
+
# User.expire! 1.week.from_now
|
44
|
+
# @note +expired_at+ can be in the future as well
|
45
|
+
def expire!(at = Time.now.utc)
|
46
|
+
self.expired_at = at
|
47
|
+
save(:validate => false)
|
48
|
+
end
|
59
49
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
50
|
+
# Overwrites active_for_authentication? from Devise::Models::Activatable
|
51
|
+
# for verifying whether a user is active to sign in or not. If the account
|
52
|
+
# is expired, it should never be allowed.
|
53
|
+
#
|
54
|
+
# @return [bool]
|
55
|
+
def active_for_authentication?
|
56
|
+
super && !self.expired?
|
57
|
+
end
|
65
58
|
|
59
|
+
# The message sym, if {#active_for_authentication?} returns +false+. E.g. needed
|
60
|
+
# for i18n.
|
61
|
+
def inactive_message
|
62
|
+
!self.expired? ? super : :expired
|
66
63
|
end
|
67
64
|
|
68
65
|
module ClassMethods
|
@@ -1,68 +1,61 @@
|
|
1
|
-
module Devise
|
2
|
-
module Models
|
1
|
+
module Devise
|
2
|
+
module Models
|
3
3
|
|
4
4
|
# PasswordArchivable
|
5
5
|
module PasswordArchivable
|
6
|
+
extend ActiveSupport::Concern
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
include InstanceMethods
|
12
|
-
has_many :old_passwords, :as => :password_archivable, :dependent => :destroy
|
13
|
-
before_update :archive_password
|
14
|
-
validate :validate_password_archive
|
15
|
-
end
|
8
|
+
included do
|
9
|
+
has_many :old_passwords, :as => :password_archivable, :dependent => :destroy
|
10
|
+
before_update :archive_password
|
11
|
+
validate :validate_password_archive
|
16
12
|
end
|
17
13
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
self.errors.add(:password, :taken_in_past) if encrypted_password_changed? and password_archive_included?
|
22
|
-
end
|
14
|
+
def validate_password_archive
|
15
|
+
self.errors.add(:password, :taken_in_past) if encrypted_password_changed? and password_archive_included?
|
16
|
+
end
|
23
17
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
end
|
18
|
+
# validate is the password used in the past
|
19
|
+
def password_archive_included?
|
20
|
+
unless self.class.deny_old_passwords.is_a? Fixnum
|
21
|
+
if self.class.deny_old_passwords.is_a? TrueClass and self.class.password_archiving_count > 0
|
22
|
+
self.class.deny_old_passwords = self.class.password_archiving_count
|
23
|
+
else
|
24
|
+
self.class.deny_old_passwords = 0
|
32
25
|
end
|
26
|
+
end
|
33
27
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
28
|
+
if self.class.deny_old_passwords > 0 and not self.password.nil?
|
29
|
+
self.old_passwords.reverse_order(:id).limit(self.class.deny_old_passwords).each do |old_password|
|
30
|
+
dummy = self.class.new
|
31
|
+
dummy.encrypted_password = old_password.encrypted_password
|
32
|
+
dummy.password_salt = old_password.password_salt if dummy.respond_to?(:password_salt)
|
33
|
+
return true if dummy.valid_password?(self.password)
|
41
34
|
end
|
42
|
-
|
43
|
-
false
|
44
35
|
end
|
45
36
|
|
46
|
-
|
37
|
+
false
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
47
41
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
else
|
55
|
-
self.old_passwords.create! :encrypted_password => self.encrypted_password_change.first
|
56
|
-
end
|
57
|
-
self.old_passwords.order('created_at DESC').offset(self.class.password_archiving_count).destroy_all
|
42
|
+
# archive the last password before save and delete all to old passwords from archive
|
43
|
+
def archive_password
|
44
|
+
if self.encrypted_password_changed?
|
45
|
+
if self.class.password_archiving_count.to_i > 0
|
46
|
+
if self.respond_to?(:password_salt_change) and not self.password_salt_change.nil?
|
47
|
+
self.old_passwords.create! :encrypted_password => self.encrypted_password_change.first, :password_salt => self.password_salt_change.first
|
58
48
|
else
|
59
|
-
self.old_passwords.
|
49
|
+
self.old_passwords.create! :encrypted_password => self.encrypted_password_change.first
|
60
50
|
end
|
51
|
+
self.old_passwords.reverse_order(:id).offset(self.class.password_archiving_count).destroy_all
|
52
|
+
else
|
53
|
+
self.old_passwords.destroy_all
|
61
54
|
end
|
62
55
|
end
|
63
56
|
end
|
64
57
|
|
65
|
-
module ClassMethods
|
58
|
+
module ClassMethods
|
66
59
|
::Devise::Models.config(self, :password_archiving_count, :deny_old_passwords)
|
67
60
|
end
|
68
61
|
end
|
@@ -1,63 +1,57 @@
|
|
1
1
|
require 'devise_security_extension/hooks/password_expirable'
|
2
2
|
|
3
|
-
module Devise
|
4
|
-
module Models
|
3
|
+
module Devise
|
4
|
+
module Models
|
5
5
|
|
6
6
|
# PasswordExpirable takes care of change password after
|
7
7
|
module PasswordExpirable
|
8
|
+
extend ActiveSupport::Concern
|
8
9
|
|
9
|
-
|
10
|
-
|
10
|
+
included do
|
11
|
+
before_save :update_password_changed
|
12
|
+
end
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
14
|
+
# is an password change required?
|
15
|
+
def need_change_password?
|
16
|
+
if self.class.expire_password_after.is_a? Fixnum or self.class.expire_password_after.is_a? Float
|
17
|
+
self.password_changed_at.nil? or self.password_changed_at < self.class.expire_password_after.ago
|
18
|
+
else
|
19
|
+
false
|
15
20
|
end
|
16
21
|
end
|
17
22
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
self.password_changed_at.nil? or self.password_changed_at < self.class.expire_password_after.ago
|
24
|
-
else
|
25
|
-
false
|
26
|
-
end
|
23
|
+
# set a fake datetime so a password change is needed and save the record
|
24
|
+
def need_change_password!
|
25
|
+
if self.class.expire_password_after.is_a? Fixnum or self.class.expire_password_after.is_a? Float
|
26
|
+
need_change_password
|
27
|
+
self.save(:validate => false)
|
27
28
|
end
|
29
|
+
end
|
28
30
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
self.save(:validate => false)
|
34
|
-
end
|
31
|
+
# set a fake datetime so a password change is needed
|
32
|
+
def need_change_password
|
33
|
+
if self.class.expire_password_after.is_a? Fixnum or self.class.expire_password_after.is_a? Float
|
34
|
+
self.password_changed_at = self.class.expire_password_after.ago
|
35
35
|
end
|
36
36
|
|
37
|
-
# set
|
38
|
-
|
39
|
-
if self.class.expire_password_after.is_a? Fixnum
|
40
|
-
self.password_changed_at = self.class.expire_password_after.ago
|
41
|
-
end
|
42
|
-
|
43
|
-
# is date not set it will set default to need set new password next login
|
44
|
-
need_change_password if self.password_changed_at.nil?
|
37
|
+
# is date not set it will set default to need set new password next login
|
38
|
+
need_change_password if self.password_changed_at.nil?
|
45
39
|
|
46
|
-
|
47
|
-
|
40
|
+
self.password_changed_at
|
41
|
+
end
|
48
42
|
|
49
|
-
|
43
|
+
private
|
50
44
|
|
51
45
|
# is password changed then update password_cahanged_at
|
52
46
|
def update_password_changed
|
53
47
|
self.password_changed_at = Time.now if (self.new_record? or self.encrypted_password_changed?) and not self.password_changed_at_changed?
|
54
48
|
end
|
55
|
-
end
|
56
49
|
|
57
|
-
module ClassMethods
|
50
|
+
module ClassMethods
|
58
51
|
::Devise::Models.config(self, :expire_password_after)
|
59
52
|
end
|
60
53
|
end
|
54
|
+
|
61
55
|
end
|
62
56
|
|
63
57
|
end
|
@@ -11,6 +11,7 @@ module Devise
|
|
11
11
|
# * +password_regex+: need strong password. Defaults to /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/
|
12
12
|
#
|
13
13
|
module SecureValidatable
|
14
|
+
|
14
15
|
def self.included(base)
|
15
16
|
base.extend ClassMethods
|
16
17
|
assert_secure_validations_api!(base)
|
@@ -22,6 +23,7 @@ module Devise
|
|
22
23
|
|
23
24
|
# validates email
|
24
25
|
validates :email, :presence => true, :if => :email_required?
|
26
|
+
validates :email, :uniqueness => true, :allow_blank => true, :if => :email_changed? # check uniq for email ever
|
25
27
|
validates :email, :email => email_validation if email_validation # use rails_email_validator or similar
|
26
28
|
|
27
29
|
# validates password
|
@@ -32,7 +34,7 @@ module Devise
|
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
35
|
-
def self.assert_secure_validations_api!(base)
|
37
|
+
def self.assert_secure_validations_api!(base)
|
36
38
|
raise "Could not use SecureValidatable on #{base}" unless base.respond_to?(:validates)
|
37
39
|
end
|
38
40
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'devise_security_extension/hooks/session_limitable'
|
2
2
|
|
3
|
-
module Devise
|
4
|
-
module Models
|
3
|
+
module Devise
|
4
|
+
module Models
|
5
5
|
# SessionLimited ensures, that there is only one session usable per account at once.
|
6
6
|
# If someone logs in, and some other is logging in with the same credentials,
|
7
7
|
# the session from the first one is invalidated and not usable anymore.
|
@@ -1,13 +1,18 @@
|
|
1
1
|
module DeviseSecurityExtension
|
2
2
|
module Patches
|
3
|
-
autoload :
|
3
|
+
autoload :UnlocksControllerCaptcha, 'devise_security_extension/patches/unlocks_controller_captcha'
|
4
|
+
autoload :PasswordsControllerCaptcha, 'devise_security_extension/patches/passwords_controller_captcha'
|
5
|
+
autoload :SessionsControllerCaptcha, 'devise_security_extension/patches/sessions_controller_captcha'
|
6
|
+
autoload :RegistrationsControllerCaptcha, 'devise_security_extension/patches/registrations_controller_captcha'
|
7
|
+
autoload :ConfirmationsControllerCaptcha, 'devise_security_extension/patches/confirmations_controller_captcha'
|
4
8
|
|
5
9
|
class << self
|
6
10
|
def apply
|
7
|
-
Devise::PasswordsController.send(:include, Patches::
|
8
|
-
Devise::UnlocksController.send(:include, Patches::
|
9
|
-
Devise::RegistrationsController.send(:include, Patches::
|
10
|
-
Devise::SessionsController.send(:include, Patches::
|
11
|
+
Devise::PasswordsController.send(:include, Patches::PasswordsControllerCaptcha) if Devise.captcha_for_recover
|
12
|
+
Devise::UnlocksController.send(:include, Patches::UnlocksControllerCaptcha) if Devise.captcha_for_unlock
|
13
|
+
Devise::RegistrationsController.send(:include, Patches::RegistrationsControllerCaptcha) if Devise.captcha_for_sign_up
|
14
|
+
Devise::SessionsController.send(:include, Patches::SessionsControllerCaptcha) if Devise.captcha_for_sign_in
|
15
|
+
Devise::ConfirmationsController.send(:include, Patches::ConfirmationsControllerCaptcha) if Devise.captcha_for_confirmation
|
11
16
|
end
|
12
17
|
end
|
13
18
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module DeviseSecurityExtension::Patches
|
2
|
+
module ConfirmationsControllerCaptcha
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
define_method :create do
|
6
|
+
if valid_captcha? params[:captcha]
|
7
|
+
self.resource = resource_class.send_confirmation_instructions(params[resource_name])
|
8
|
+
|
9
|
+
if successfully_sent?(resource)
|
10
|
+
respond_with({}, :location => after_resending_confirmation_instructions_path_for(resource_name))
|
11
|
+
else
|
12
|
+
respond_with(resource)
|
13
|
+
end
|
14
|
+
else
|
15
|
+
flash[:alert] = t('devise.invalid_captcha') if is_navigational_format?
|
16
|
+
respond_with({}, :location => new_confirmation_path(resource_name))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module DeviseSecurityExtension::Patches
|
2
|
+
module PasswordsControllerCaptcha
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
define_method :create do
|
6
|
+
if valid_captcha? params[:captcha]
|
7
|
+
self.resource = resource_class.send_reset_password_instructions(params[resource_name])
|
8
|
+
if successfully_sent?(resource)
|
9
|
+
respond_with({}, :location => new_session_path(resource_name))
|
10
|
+
else
|
11
|
+
respond_with(resource)
|
12
|
+
end
|
13
|
+
else
|
14
|
+
flash[:alert] = t('devise.invalid_captcha') if is_navigational_format?
|
15
|
+
respond_with({}, :location => new_password_path(resource_name))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module DeviseSecurityExtension::Patches
|
2
|
+
module RegistrationsControllerCaptcha
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
define_method :create do
|
6
|
+
build_resource
|
7
|
+
|
8
|
+
if valid_captcha? params[:captcha]
|
9
|
+
|
10
|
+
if resource.save
|
11
|
+
if resource.active_for_authentication?
|
12
|
+
set_flash_message :notice, :signed_up if is_navigational_format?
|
13
|
+
sign_in(resource_name, resource)
|
14
|
+
respond_with resource, :location => after_sign_up_path_for(resource)
|
15
|
+
else
|
16
|
+
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_navigational_format?
|
17
|
+
expire_session_data_after_sign_in!
|
18
|
+
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
|
19
|
+
end
|
20
|
+
else
|
21
|
+
clean_up_passwords resource
|
22
|
+
respond_with resource
|
23
|
+
end
|
24
|
+
|
25
|
+
else
|
26
|
+
resource.errors.add :base, t('devise.invalid_captcha')
|
27
|
+
clean_up_passwords resource
|
28
|
+
respond_with resource
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module DeviseSecurityExtension::Patches
|
2
|
+
module SessionsControllerCaptcha
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
define_method :create do
|
6
|
+
if valid_captcha? params[:captcha]
|
7
|
+
resource = warden.authenticate!(auth_options)
|
8
|
+
set_flash_message(:notice, :signed_in) if is_navigational_format?
|
9
|
+
sign_in(resource_name, resource)
|
10
|
+
respond_with resource, :location => after_sign_in_path_for(resource)
|
11
|
+
else
|
12
|
+
flash[:alert] = t('devise.invalid_captcha') if is_navigational_format?
|
13
|
+
respond_with({}, :location => new_session_path(resource_name))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# for bad protected use in controller
|
18
|
+
define_method :auth_options do
|
19
|
+
{ :scope => resource_name, :recall => "#{controller_path}#new" }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module DeviseSecurityExtension::Patches
|
2
|
+
module UnlocksControllerCaptcha
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
included do
|
5
|
+
define_method :create do
|
6
|
+
if valid_captcha? params[:captcha]
|
7
|
+
self.resource = resource_class.send_unlock_instructions(params[resource_name])
|
8
|
+
if successfully_sent?(resource)
|
9
|
+
respond_with({}, :location => new_session_path(resource_name))
|
10
|
+
else
|
11
|
+
respond_with(resource)
|
12
|
+
end
|
13
|
+
else
|
14
|
+
flash[:alert] = t('devise.invalid_captcha') if is_navigational_format?
|
15
|
+
respond_with({}, :location => new_unlock_path(resource_name))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module DeviseSecurityExtension
|
2
|
-
module Generators
|
2
|
+
module Generators
|
3
3
|
# Install Generator
|
4
4
|
class InstallGenerator < Rails::Generators::Base
|
5
5
|
source_root File.expand_path("../../templates", __FILE__)
|
@@ -27,9 +27,10 @@ module DeviseSecurityExtension
|
|
27
27
|
" # config.captcha_for_sign_in = true\n\n" +
|
28
28
|
" # captcha integration for unlock form\n" +
|
29
29
|
" # config.captcha_for_unlock = true\n\n" +
|
30
|
-
" #
|
30
|
+
" # captcha integration for confirmation form\n" +
|
31
|
+
" # config.captcha_for_confirmation = true\n\n" +
|
31
32
|
" # Time period for account expiry from last_activity_at\n" +
|
32
|
-
" config.expire_after = 90.days\n" +
|
33
|
+
" # config.expire_after = 90.days\n\n" +
|
33
34
|
"", :before => /end[ |\n|]+\Z/
|
34
35
|
end
|
35
36
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise_security_extension
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2012-06-06 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rails
|
17
|
-
requirement:
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,21 +22,31 @@ dependencies:
|
|
22
22
|
version: 3.1.1
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements:
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: 3.1.1
|
26
31
|
- !ruby/object:Gem::Dependency
|
27
32
|
name: devise
|
28
|
-
requirement:
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
29
34
|
none: false
|
30
35
|
requirements:
|
31
36
|
- - ! '>='
|
32
37
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
38
|
+
version: 2.0.0
|
34
39
|
type: :runtime
|
35
40
|
prerelease: false
|
36
|
-
version_requirements:
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 2.0.0
|
37
47
|
- !ruby/object:Gem::Dependency
|
38
48
|
name: rails_email_validator
|
39
|
-
requirement:
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
40
50
|
none: false
|
41
51
|
requirements:
|
42
52
|
- - ! '>='
|
@@ -44,10 +54,15 @@ dependencies:
|
|
44
54
|
version: '0'
|
45
55
|
type: :development
|
46
56
|
prerelease: false
|
47
|
-
version_requirements:
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
48
63
|
- !ruby/object:Gem::Dependency
|
49
64
|
name: easy_captcha
|
50
|
-
requirement:
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
51
66
|
none: false
|
52
67
|
requirements:
|
53
68
|
- - ! '>='
|
@@ -55,10 +70,15 @@ dependencies:
|
|
55
70
|
version: '0'
|
56
71
|
type: :development
|
57
72
|
prerelease: false
|
58
|
-
version_requirements:
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
59
79
|
- !ruby/object:Gem::Dependency
|
60
80
|
name: bundler
|
61
|
-
requirement:
|
81
|
+
requirement: !ruby/object:Gem::Requirement
|
62
82
|
none: false
|
63
83
|
requirements:
|
64
84
|
- - ~>
|
@@ -66,10 +86,15 @@ dependencies:
|
|
66
86
|
version: 1.0.0
|
67
87
|
type: :development
|
68
88
|
prerelease: false
|
69
|
-
version_requirements:
|
89
|
+
version_requirements: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ~>
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 1.0.0
|
70
95
|
- !ruby/object:Gem::Dependency
|
71
96
|
name: jeweler
|
72
|
-
requirement:
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
73
98
|
none: false
|
74
99
|
requirements:
|
75
100
|
- - ~>
|
@@ -77,7 +102,12 @@ dependencies:
|
|
77
102
|
version: 1.5.2
|
78
103
|
type: :development
|
79
104
|
prerelease: false
|
80
|
-
version_requirements:
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
none: false
|
107
|
+
requirements:
|
108
|
+
- - ~>
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 1.5.2
|
81
111
|
description: An enterprise security extension for devise, trying to meet industrial
|
82
112
|
standard security demands for web applications.
|
83
113
|
email: team@phatworx.de
|
@@ -112,7 +142,11 @@ files:
|
|
112
142
|
- lib/devise_security_extension/models/session_limitable.rb
|
113
143
|
- lib/devise_security_extension/orm/active_record.rb
|
114
144
|
- lib/devise_security_extension/patches.rb
|
115
|
-
- lib/devise_security_extension/patches/
|
145
|
+
- lib/devise_security_extension/patches/confirmations_controller_captcha.rb
|
146
|
+
- lib/devise_security_extension/patches/passwords_controller_captcha.rb
|
147
|
+
- lib/devise_security_extension/patches/registrations_controller_captcha.rb
|
148
|
+
- lib/devise_security_extension/patches/sessions_controller_captcha.rb
|
149
|
+
- lib/devise_security_extension/patches/unlocks_controller_captcha.rb
|
116
150
|
- lib/devise_security_extension/rails.rb
|
117
151
|
- lib/devise_security_extension/routes.rb
|
118
152
|
- lib/devise_security_extension/schema.rb
|
@@ -134,7 +168,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
134
168
|
version: '0'
|
135
169
|
segments:
|
136
170
|
- 0
|
137
|
-
hash: -
|
171
|
+
hash: -3249260859492066288
|
138
172
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
173
|
none: false
|
140
174
|
requirements:
|
@@ -143,7 +177,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
143
177
|
version: '0'
|
144
178
|
requirements: []
|
145
179
|
rubyforge_project:
|
146
|
-
rubygems_version: 1.8.
|
180
|
+
rubygems_version: 1.8.21
|
147
181
|
signing_key:
|
148
182
|
specification_version: 3
|
149
183
|
summary: Security extension for devise
|
@@ -1,21 +0,0 @@
|
|
1
|
-
module DeviseSecurityExtension::Patches
|
2
|
-
# patch passwords controller for captcha
|
3
|
-
module ControllerCaptcha
|
4
|
-
extend ActiveSupport::Concern
|
5
|
-
included do
|
6
|
-
# here the patch
|
7
|
-
|
8
|
-
alias_method :create_without_captcha_check, :create
|
9
|
-
define_method :create do
|
10
|
-
if valid_captcha? params[:captcha]
|
11
|
-
create_without_captcha_check
|
12
|
-
else
|
13
|
-
build_resource
|
14
|
-
clean_up_passwords(resource)
|
15
|
-
flash[:alert] = I18n.translate('devise.invalid_captcha')
|
16
|
-
render_with_scope :new
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|