devise_security_extension 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
- * t.password_expirable
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.2.1
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.2.1"
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-03}
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,3 @@
1
+ class OldPassword < ActiveRecord::Base
2
+ belongs_to :password_archivable, :polymorphic => true
3
+ end
@@ -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 # config.expire_password_after = false\n" +
12
- " # Need 1 char of A-Z, a-z and 0-9\n # config.password_regex = /(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])/\n" +
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.2.1
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-03 00:00:00 +01:00
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: -219664376672679260
132
+ hash: -461004346872330403
131
133
  segments:
132
134
  - 0
133
135
  version: "0"