devise_security_extension 0.2.1 → 0.3.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.
- data/README.rdoc +15 -1
- data/VERSION +1 -1
- data/devise_security_extension.gemspec +4 -2
- data/lib/devise_security_extension.rb +11 -0
- data/lib/devise_security_extension/models/old_password.rb +3 -0
- data/lib/devise_security_extension/models/password_archivable.rb +67 -0
- data/lib/devise_security_extension/schema.rb +18 -1
- data/lib/generators/devise_security_extension/install_generator.rb +6 -2
- metadata +5 -3
data/README.rdoc
CHANGED
@@ -23,10 +23,22 @@ after bundle execute
|
|
23
23
|
|
24
24
|
* :password_expirable - activate that passwords will expire
|
25
25
|
* :secure_validatable - better way to validate model. don't use with :validatable!!!
|
26
|
+
* :password_archivable - save password in old_passwords for history checks
|
26
27
|
|
27
28
|
== Schema
|
28
29
|
|
29
|
-
|
30
|
+
=== Password expirable
|
31
|
+
|
32
|
+
create_table :the_resources do |t|
|
33
|
+
t.password_expirable
|
34
|
+
end
|
35
|
+
|
36
|
+
=== Password archive
|
37
|
+
|
38
|
+
create_table :old_passwords do
|
39
|
+
t.password_archivable
|
40
|
+
end
|
41
|
+
add_index :old_passwords, [:password_archivable_type, :password_archivable_id], :name => :index_password_archivable
|
30
42
|
|
31
43
|
== Requirements
|
32
44
|
|
@@ -37,6 +49,7 @@ after bundle execute
|
|
37
49
|
|
38
50
|
* expire passwords (update password with current password)
|
39
51
|
* strong password validation
|
52
|
+
* save old passwords for check new passwords
|
40
53
|
|
41
54
|
== Todo
|
42
55
|
|
@@ -48,6 +61,7 @@ after bundle execute
|
|
48
61
|
== History
|
49
62
|
* 0.1 expire passwords
|
50
63
|
* 0.2 strong password validation
|
64
|
+
* 0.3 password archivable with validation
|
51
65
|
|
52
66
|
== Maintainers
|
53
67
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{devise_security_extension}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.0"
|
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"]
|
12
|
-
s.date = %q{2011-02-
|
12
|
+
s.date = %q{2011-02-13}
|
13
13
|
s.description = %q{a gem for extend devise for more password security}
|
14
14
|
s.email = %q{develop@marco-scholl.de}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -32,6 +32,8 @@ Gem::Specification.new do |s|
|
|
32
32
|
"lib/devise_security_extension.rb",
|
33
33
|
"lib/devise_security_extension/controllers/helpers.rb",
|
34
34
|
"lib/devise_security_extension/hooks/password_expirable.rb",
|
35
|
+
"lib/devise_security_extension/models/old_password.rb",
|
36
|
+
"lib/devise_security_extension/models/password_archivable.rb",
|
35
37
|
"lib/devise_security_extension/models/password_expirable.rb",
|
36
38
|
"lib/devise_security_extension/models/secure_validatable.rb",
|
37
39
|
"lib/devise_security_extension/orm/active_record.rb",
|
@@ -1,6 +1,8 @@
|
|
1
1
|
#require 'rails/all'
|
2
2
|
require 'active_record/connection_adapters/abstract/schema_definitions'
|
3
3
|
require 'active_support/core_ext/integer'
|
4
|
+
require 'active_support/ordered_hash'
|
5
|
+
require 'active_support/concern'
|
4
6
|
require 'devise'
|
5
7
|
|
6
8
|
module Devise # :nodoc:
|
@@ -13,6 +15,13 @@ module Devise # :nodoc:
|
|
13
15
|
mattr_accessor :password_regex
|
14
16
|
@@password_regex = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/
|
15
17
|
|
18
|
+
# write history of last x passwords
|
19
|
+
mattr_accessor :password_archiving_count
|
20
|
+
@@password_archiving_count = 5
|
21
|
+
|
22
|
+
# deny old password (true, false, integer)
|
23
|
+
mattr_accessor :deny_old_passwords
|
24
|
+
@@deny_old_passwords = true
|
16
25
|
end
|
17
26
|
|
18
27
|
# an security extension for devise
|
@@ -26,7 +35,9 @@ end
|
|
26
35
|
|
27
36
|
Devise.add_module :password_expirable, :controller => :password_expirable, :model => 'devise_security_extension/models/password_expirable', :route => :password_expired
|
28
37
|
Devise.add_module :secure_validatable, :model => 'devise_security_extension/models/secure_validatable'
|
38
|
+
Devise.add_module :password_archivable, :model => 'devise_security_extension/models/password_archivable'
|
29
39
|
|
30
40
|
require 'devise_security_extension/routes'
|
31
41
|
require 'devise_security_extension/rails'
|
32
42
|
require 'devise_security_extension/orm/active_record'
|
43
|
+
require 'devise_security_extension/models/old_password'
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Devise # :nodoc:
|
2
|
+
module Models # :nodoc:
|
3
|
+
|
4
|
+
# PasswordArchivable
|
5
|
+
module PasswordArchivable
|
6
|
+
|
7
|
+
def self.included(base) # :nodoc:
|
8
|
+
base.extend ClassMethods
|
9
|
+
|
10
|
+
base.class_eval do
|
11
|
+
include InstanceMethods
|
12
|
+
has_many :old_passwords, :as => :password_archivable, :class_name => "OldPassword"
|
13
|
+
before_save :archive_password
|
14
|
+
validate :validate_password_archive
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module InstanceMethods # :nodoc:
|
19
|
+
|
20
|
+
def validate_password_archive
|
21
|
+
self.errors.add(:password, :taken_in_past) if password_archive_included?
|
22
|
+
end
|
23
|
+
|
24
|
+
# validate is the password used in the past
|
25
|
+
def password_archive_included?
|
26
|
+
unless self.class.deny_old_passwords.is_a? Fixnum
|
27
|
+
if self.class.deny_old_passwords.is_a? TrueClass and self.class.password_archiving_count > 0
|
28
|
+
self.class.deny_old_passwords = self.class.password_archiving_count
|
29
|
+
else
|
30
|
+
self.class.deny_old_passwords = 0
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
if self.class.deny_old_passwords > 0 and not self.password.nil?
|
35
|
+
self.old_passwords.order('created_at DESC').limit(self.class.deny_old_passwords).limit(self.class.deny_old_passwords).each do |old_password|
|
36
|
+
dummy = self.class.new
|
37
|
+
dummy.encrypted_password = old_password.encrypted_password
|
38
|
+
dummy.password_salt = old_password.password_salt
|
39
|
+
return true if dummy.valid_password?(self.password)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
false
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# archive the last password before save and delete all to old passwords from archive
|
49
|
+
def archive_password
|
50
|
+
if self.encrypted_password_changed?
|
51
|
+
if self.class.password_archiving_count.to_i > 0
|
52
|
+
self.old_passwords.create! :encrypted_password => self.encrypted_password_change.first, :password_salt => self.password_salt_change.first
|
53
|
+
self.old_passwords.order('created_at DESC').offset(self.class.password_archiving_count).destroy_all
|
54
|
+
else
|
55
|
+
self.old_passwords.destroy_all
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
module ClassMethods #:nodoc:
|
62
|
+
::Devise::Models.config(self, :password_archiving_count, :deny_old_passwords)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -6,7 +6,7 @@ module DeviseSecurityExtension
|
|
6
6
|
# Examples
|
7
7
|
#
|
8
8
|
# # For a new resource migration:
|
9
|
-
# create_table :the_resources do
|
9
|
+
# create_table :the_resources do |t|
|
10
10
|
# t.password_expirable
|
11
11
|
# ...
|
12
12
|
# end
|
@@ -19,5 +19,22 @@ module DeviseSecurityExtension
|
|
19
19
|
def password_expirable
|
20
20
|
apply_devise_schema :password_changed_at, DateTime
|
21
21
|
end
|
22
|
+
|
23
|
+
# Add password_archivable columns
|
24
|
+
#
|
25
|
+
# Examples
|
26
|
+
#
|
27
|
+
# create_table :old_passwords do
|
28
|
+
# t.password_archivable
|
29
|
+
# end
|
30
|
+
# add_index :old_passwords, [:password_archivable_type, :password_archivable_id], :name => :index_password_archivable
|
31
|
+
#
|
32
|
+
def password_archivable
|
33
|
+
apply_devise_schema :encrypted_password, String, :limit => 128, :null => false
|
34
|
+
apply_devise_schema :password_salt, String, :null => false
|
35
|
+
apply_devise_schema :password_archivable_id, Integer, :null => false
|
36
|
+
apply_devise_schema :password_archivable_type, String, :null => false
|
37
|
+
apply_devise_schema :created_at, DateTime
|
38
|
+
end
|
22
39
|
end
|
23
40
|
end
|
@@ -8,8 +8,12 @@ module DeviseSecurityExtension
|
|
8
8
|
|
9
9
|
def add_configs
|
10
10
|
inject_into_file "config/initializers/devise.rb", "\n\n # ==> Security Extension\n # Configure security extension for devise\n\n" +
|
11
|
-
" # Should the password expire (e.g 3.months)\n
|
12
|
-
" #
|
11
|
+
" # Should the password expire (e.g 3.months)\n" +
|
12
|
+
" # config.expire_password_after = false\n" +
|
13
|
+
" # Need 1 char of A-Z, a-z and 0-9\n" +
|
14
|
+
" # config.password_regex = /(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])/\n" +
|
15
|
+
" # How often save old passwords in archive\n" +
|
16
|
+
" # config.password_archiving_count = 5\n" +
|
13
17
|
"\n", :before => /end[ |\n|]+\Z/
|
14
18
|
end
|
15
19
|
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: devise_security_extension
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.
|
5
|
+
version: 0.3.0
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Marco Scholl
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-02-
|
13
|
+
date: 2011-02-13 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -104,6 +104,8 @@ files:
|
|
104
104
|
- lib/devise_security_extension.rb
|
105
105
|
- lib/devise_security_extension/controllers/helpers.rb
|
106
106
|
- lib/devise_security_extension/hooks/password_expirable.rb
|
107
|
+
- lib/devise_security_extension/models/old_password.rb
|
108
|
+
- lib/devise_security_extension/models/password_archivable.rb
|
107
109
|
- lib/devise_security_extension/models/password_expirable.rb
|
108
110
|
- lib/devise_security_extension/models/secure_validatable.rb
|
109
111
|
- lib/devise_security_extension/orm/active_record.rb
|
@@ -127,7 +129,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
127
129
|
requirements:
|
128
130
|
- - ">="
|
129
131
|
- !ruby/object:Gem::Version
|
130
|
-
hash: -
|
132
|
+
hash: -461004346872330403
|
131
133
|
segments:
|
132
134
|
- 0
|
133
135
|
version: "0"
|