devise_password_history 0.1.2 → 0.2.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/Gemfile CHANGED
@@ -1,4 +1,10 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in devise_password_history.gemspec
4
3
  gemspec
4
+
5
+ group :test do
6
+ gem "rake"
7
+ gem "turn"
8
+ gem "mocha"
9
+ gem "minitest"
10
+ end
data/README.md CHANGED
@@ -30,6 +30,7 @@ That generator will do three things:
30
30
  1. Modifies the `config/initializers/devise.rb` file with two new config options:
31
31
  - `config.deny_old_passwords`: turns the validations on/off
32
32
  - `config.password_history_count`: the threshold of how many passwords to store
33
+ - `config.password_age`: ability to force password expiration (ex: `90.days`)
33
34
  2. Creates an `OldPassword` polymorphic model in `app/models`
34
35
  3. Creates the migration for the `old_passwords` table
35
36
 
@@ -44,6 +45,30 @@ any of the other extensions:
44
45
  devise :database_authenticatable, :password_history
45
46
  end
46
47
 
48
+ ## Notes on Password Age/Expiration
49
+
50
+ By default, the `password_age` is set to `nil` (which turns this feature off).
51
+ If you want to use it, set it to how often you want passwords to expire, an
52
+ example might be `90.days`.
53
+
54
+ If a password has expired, the user will be redirected to a
55
+ `update_password_path` route, which defaults to `edit_admin_user_path(current_user)`.
56
+ You can override this in `ApplicationController` as needed.
57
+
58
+ class ApplicationController
59
+ # ...
60
+
61
+ protected
62
+ def update_password_path
63
+ your_custom_route_goes_here_path
64
+ end
65
+ end
66
+
67
+ Additionally, the filter that runs to check expired passwords is
68
+ `check_password_expiration`. To prevent this filter from running on the
69
+ controller that does the password updates, you should
70
+ `skip_before_filter :check_password_expiration`.
71
+
47
72
  ## Contributing
48
73
 
49
74
  1. Fork it
@@ -10,7 +10,7 @@ Gem::Specification.new do |gem|
10
10
  gem.email = ["ryan@rpheath.com"]
11
11
  gem.description = %q{Maintains password history and ensures old passwords aren't reused}
12
12
  gem.summary = %q{Password history support for devise}
13
- gem.homepage = ""
13
+ gem.homepage = "http://github.com/rpheath/devise_password_history"
14
14
 
15
15
  gem.add_dependency("devise", ["~> 2.2.0"])
16
16
 
@@ -0,0 +1,41 @@
1
+ module DevisePasswordHistory
2
+ module Controllers
3
+ module Helpers
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ append_before_filter :check_password_expiration
8
+ end
9
+
10
+ protected
11
+ def check_password_expiration
12
+ # skip if we don't have a user
13
+ return if current_user.blank?
14
+ # skip if we're on the controller that needs
15
+ # to update the passwords (infinite loop otherwise)
16
+ return if self.class.to_s == update_password_controller.to_s
17
+
18
+ if current_user.has_password_expired?
19
+ flash[:alert] = expired_password_message
20
+ redirect_to update_password_path
21
+ end
22
+ end
23
+
24
+ # path to update passwords (can be overridden)
25
+ def update_password_path
26
+ edit_admin_user_path(current_user)
27
+ end
28
+
29
+ # the controller that handles password
30
+ # updating (can be overridden)
31
+ def update_password_controller
32
+ "Admin::UsersController"
33
+ end
34
+
35
+ # flash message
36
+ def expired_password_message
37
+ "Your password has expired, please choose a new one"
38
+ end
39
+ end
40
+ end
41
+ end
@@ -20,6 +20,8 @@ module DevisePasswordHistory
20
20
  " config.password_history_count = 8\n\n" +
21
21
  " # Toggles behavior for Deny/Allow old passwords\n" +
22
22
  " config.deny_old_passwords = true\n\n" +
23
+ " # Repeatedly forces a new password based on this age\n" +
24
+ " # config.password_age = 90.days\n\n" +
23
25
  "", :before => /end[\s|\n|]+\Z/
24
26
  end
25
27
 
@@ -6,7 +6,7 @@ module Devise
6
6
  extend ActiveSupport::Concern
7
7
 
8
8
  module ClassMethods
9
- Devise::Models.config(self, :password_history_count, :deny_old_passwords)
9
+ Devise::Models.config(self, :password_history_count, :deny_old_passwords, :password_age)
10
10
  end
11
11
 
12
12
  included do
@@ -45,6 +45,32 @@ module Devise
45
45
  false
46
46
  end
47
47
 
48
+ def has_password_expired?
49
+ # make sure this feature is turned on
50
+ return false if self.class.password_age.nil?
51
+
52
+ # initializing to ensure expired_stamp
53
+ # exists in case conditions fail below
54
+ expired_stamp = Time.now
55
+
56
+ if self.old_passwords.present?
57
+ # since we are tracking old passwords, we can get the
58
+ # last time the password was changed
59
+ password_changed_at = self.old_passwords.order(:created_at).last.created_at
60
+ # our expired stamp is the password age past the last password change
61
+ expired_stamp = password_changed_at + self.class.password_age
62
+ else
63
+ # if no old passwords exist yet, we can check against
64
+ # when the user was created and use that timestamp
65
+ if self.respond_to?(:created_at)
66
+ expired_stamp = self.created_at + self.class.password_age
67
+ end
68
+ end
69
+
70
+ # are we expired?
71
+ !!(Time.now > expired_stamp)
72
+ end
73
+
48
74
  protected
49
75
  # make sure this is turned on in the Devise config
50
76
  def should_deny_old_passwords?
@@ -0,0 +1,7 @@
1
+ module DevisePasswordHistory
2
+ class Engine < Rails::Engine
3
+ ActiveSupport.on_load(:action_controller) do
4
+ include DevisePasswordHistory::Controllers::Helpers
5
+ end
6
+ end
7
+ end
@@ -1,3 +1,3 @@
1
1
  module DevisePasswordHistory
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -14,9 +14,19 @@ module Devise
14
14
  # Toggles the behavior of denying/allowing old passwords
15
15
  mattr_accessor :deny_old_passwords
16
16
  @@deny_old_passwords = true
17
+
18
+ # Repeatedly forces a new password based on this age
19
+ mattr_accessor :password_age
20
+ @@password_age = nil
17
21
  end
18
22
 
19
- module DevisePasswordHistory; end
23
+ module DevisePasswordHistory
24
+ module Controllers
25
+ autoload :Helpers, "devise_password_history/controllers/helpers"
26
+ end
27
+ end
20
28
 
21
29
  # makes this module available to the `devise` command
22
- Devise.add_module :password_history, :model => "devise_password_history/models/password_history"
30
+ Devise.add_module :password_history, :model => "devise_password_history/models/password_history"
31
+
32
+ require "devise_password_history/rails"
@@ -0,0 +1,9 @@
1
+ require "test/unit"
2
+ require "mocha/setup"
3
+ require "turn"
4
+
5
+ Test::Unit::TestCase.class_eval do
6
+ def self.test(name, &block)
7
+ define_method("test_#{name.to_s.gsub(/\W/,'_')}", &block) if block_given?
8
+ end
9
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise_password_history
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 23
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
9
8
  - 2
10
- version: 0.1.2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ryan Heath
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2014-01-14 00:00:00 -05:00
18
+ date: 2014-01-25 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -51,13 +51,16 @@ files:
51
51
  - Rakefile
52
52
  - devise_password_history.gemspec
53
53
  - lib/devise_password_history.rb
54
+ - lib/devise_password_history/controllers/helpers.rb
54
55
  - lib/devise_password_history/generators/install_generator.rb
55
56
  - lib/devise_password_history/generators/templates/migrations/create_old_passwords.rb
56
57
  - lib/devise_password_history/generators/templates/models/old_password.rb
57
58
  - lib/devise_password_history/models/password_history.rb
59
+ - lib/devise_password_history/rails.rb
58
60
  - lib/devise_password_history/version.rb
61
+ - test/test_helper.rb
59
62
  has_rdoc: true
60
- homepage: ""
63
+ homepage: http://github.com/rpheath/devise_password_history
61
64
  licenses: []
62
65
 
63
66
  post_install_message:
@@ -90,5 +93,5 @@ rubygems_version: 1.6.2
90
93
  signing_key:
91
94
  specification_version: 3
92
95
  summary: Password history support for devise
93
- test_files: []
94
-
96
+ test_files:
97
+ - test/test_helper.rb