devise_security_extension 0.5.1 → 0.6.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 CHANGED
@@ -9,12 +9,13 @@ An enterprise security extension for devise, trying to meet industrial standard
9
9
  === Model modules
10
10
 
11
11
  * :password_expirable - passwords will expire after a configured time (and will need an update)
12
- * :secure_validatable - better way to validate model (email, stronger password validation). don't use with :validatable!
13
- * :password_archivable - save used password in an old_passwords table for history checks (don't be able to use a formerly used password)
14
- * :session_limitable - ensures, that there is only one session usable per account at once.
12
+ * :secure_validatable - better way to validate a model (email, stronger password validation). Don't use with :validatable!
13
+ * :password_archivable - save used passwords in an old_passwords table for history checks (don't be able to use a formerly used password)
14
+ * :session_limitable - ensures, that there is only one session usable per account at once
15
+ * :expirable - expires a user account after x days of inactivity (default 90 days)
15
16
 
16
17
  == Installation
17
- add to Gemfile
18
+ Add to Gemfile
18
19
  gem 'devise_security_extension'
19
20
 
20
21
  after bundle install
@@ -49,6 +50,10 @@ for :secure_validatable you need to add
49
50
 
50
51
  # captcha integration for unlock form
51
52
  # config.captcha_for_unlock = true
53
+
54
+ # ==> Configuration for :expirable
55
+ # Time period for account expiry from last_activity_at
56
+ config.expire_after = 90.days
52
57
  end
53
58
 
54
59
  == Captcha-Support
@@ -58,7 +63,7 @@ for :secure_validatable you need to add
58
63
  1. add to Gemfile "gem 'easy_captcha'"
59
64
  2. install easy_captcha "rails g easy_captcha:install"
60
65
  3. enable captcha - see "Configuration"
61
- 4. add captcha source in views of devise for each controller you have activate
66
+ 4. add captcha source in the devise views for each controller you have activated
62
67
 
63
68
  <p><%= captcha_tag %></p>
64
69
  <p><%= text_field_tag :captcha %></p>
@@ -87,6 +92,24 @@ That's it!
87
92
  t.session_limitable
88
93
  end
89
94
 
95
+ === Expirable
96
+ Devise 2.0 style migrations on new resource:
97
+
98
+ create_table :the_resources do |t|
99
+ ...
100
+ t.datetime :last_activity_at
101
+ t.datetime :expired_at
102
+ ...
103
+ end
104
+
105
+ Add module to existing resource with
106
+
107
+ change_table :the_resources do |t|
108
+ t.datetime :last_activity_at
109
+ t.datetime :expired_at
110
+ end
111
+
112
+
90
113
  == Requirements
91
114
 
92
115
  * devise (https://github.com/plataformatec/devise)
@@ -95,7 +118,7 @@ That's it!
95
118
 
96
119
  == Todo
97
120
 
98
- * disable inactive users after time
121
+ * see the github issues (feature requests)
99
122
 
100
123
  == History
101
124
  * 0.1 expire passwords
@@ -103,6 +126,7 @@ That's it!
103
126
  * 0.3 password archivable with validation
104
127
  * 0.4 captcha support for sign_up, sign_in, recover and unlock
105
128
  * 0.5 session_limitable module
129
+ * 0.6 expirable module
106
130
 
107
131
  == Maintainers
108
132
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.1
1
+ 0.6.0
@@ -10,3 +10,4 @@ de:
10
10
  change_required: "Ihr Passwort ist abgelaufen. Bitte vergeben sie ein neues Passwort!"
11
11
  failure:
12
12
  session_limited: 'Ihre Anmeldedaten wurden in einem anderen Browser genutzt. Bitte melden Sie sich erneut an, um in diesem Browser fortzufahren.'
13
+ expired: 'Ihr Account ist aufgrund zu langer Inaktiviät abgelaufen. Bitte kontaktieren Sie den Administrator.'
@@ -10,3 +10,4 @@ en:
10
10
  change_required: "Your password is expired. Please renew your password!"
11
11
  failure:
12
12
  session_limited: 'Your login credentials were used in another browser. Please sign in again to continue in this browser.'
13
+ expired: 'Your account has expired due to inactivity. Please contact the site administrator.'
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "devise_security_extension"
8
- s.version = "0.5.1"
8
+ s.version = "0.6.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", "Alexander Dreher"]
12
- s.date = "2011-12-27"
12
+ s.date = "2011-12-28"
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 = [
@@ -31,8 +31,10 @@ Gem::Specification.new do |s|
31
31
  "devise_security_extension.gemspec",
32
32
  "lib/devise_security_extension.rb",
33
33
  "lib/devise_security_extension/controllers/helpers.rb",
34
+ "lib/devise_security_extension/hooks/expirable.rb",
34
35
  "lib/devise_security_extension/hooks/password_expirable.rb",
35
36
  "lib/devise_security_extension/hooks/session_limitable.rb",
37
+ "lib/devise_security_extension/models/expirable.rb",
36
38
  "lib/devise_security_extension/models/old_password.rb",
37
39
  "lib/devise_security_extension/models/password_archivable.rb",
38
40
  "lib/devise_security_extension/models/password_expirable.rb",
@@ -43,7 +43,12 @@ module Devise # :nodoc:
43
43
  # captcha integration for unlock form
44
44
  mattr_accessor :captcha_for_unlock
45
45
  @@captcha_for_unlock = false
46
-
46
+
47
+ # Time period for account expiry from last_activity_at
48
+ mattr_accessor :expire_after
49
+ @@expire_after = 90.days
50
+ mattr_accessor :delete_expired_after
51
+ @@delete_expired_after = 90.days
47
52
  end
48
53
 
49
54
  # an security extension for devise
@@ -51,7 +56,7 @@ module DeviseSecurityExtension
51
56
  autoload :Schema, 'devise_security_extension/schema'
52
57
  autoload :Patches, 'devise_security_extension/patches'
53
58
 
54
- module Controllers # :nodoc:
59
+ module Controllers
55
60
  autoload :Helpers, 'devise_security_extension/controllers/helpers'
56
61
  end
57
62
  end
@@ -61,10 +66,10 @@ Devise.add_module :password_expirable, :controller => :password_expirable, :mode
61
66
  Devise.add_module :secure_validatable, :model => 'devise_security_extension/models/secure_validatable'
62
67
  Devise.add_module :password_archivable, :model => 'devise_security_extension/models/password_archivable'
63
68
  Devise.add_module :session_limitable, :model => 'devise_security_extension/models/session_limitable'
69
+ Devise.add_module :expirable, :model => 'devise_security_extension/models/expirable'
64
70
 
65
71
  # requires
66
72
  require 'devise_security_extension/routes'
67
73
  require 'devise_security_extension/rails'
68
74
  require 'devise_security_extension/orm/active_record'
69
75
  require 'devise_security_extension/models/old_password'
70
-
@@ -0,0 +1,10 @@
1
+ # Updates the last_activity_at fields from the record. Only when the user is active
2
+ # for authentication and authenticated.
3
+ # An expiry of the account is only checked on sign in OR on manually setting the
4
+ # expired_at to the past (see Devise::Models::Expirable for this)
5
+ Warden::Manager.after_set_user do |record, warden, options|
6
+ if record && record.respond_to?(:active_for_authentication?) && record.active_for_authentication? &&
7
+ warden.authenticated?(options[:scope]) && record.respond_to?(:update_last_activitiy!)
8
+ record.update_last_activitiy!
9
+ end
10
+ end
@@ -0,0 +1,124 @@
1
+ require 'devise_security_extension/hooks/expirable'
2
+
3
+ module Devise
4
+ module Models
5
+ # Deactivate the account after a configurable amount of time. To be able to
6
+ # tell, it tracks activity about your account with the following columns:
7
+ #
8
+ # * last_activity_at - A timestamp updated when the user requests a page (only signed in)
9
+ #
10
+ # == Options
11
+ # +:expire_after+ - Time interval to expire accounts after
12
+ #
13
+ # == Additions
14
+ # Best used with two cron jobs. One for expiring accounts after inactivity,
15
+ # and another, that deletes accounts, which have expired for a given amount
16
+ # of time (for example 90 days).
17
+ #
18
+ module Expirable
19
+ extend ActiveSupport::Concern
20
+
21
+ module InstanceMethods
22
+ # Updates +last_activity_at+, called from a Warden::Manager.after_set_user hook.
23
+ def update_last_activitiy!
24
+ self.last_activity_at = Time.now.utc
25
+ save(:validate => false)
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
39
+
40
+ # Expire an account. This is for cron jobs and manually expiring of accounts.
41
+ #
42
+ # @example
43
+ # User.expire!
44
+ # User.expire! 1.week.from_now
45
+ # @note +expired_at+ can be in the future as well
46
+ def expire!(at = Time.now.utc)
47
+ self.expired_at = at
48
+ save(:validate => false)
49
+ end
50
+
51
+ # Overwrites active_for_authentication? from Devise::Models::Activatable
52
+ # for verifying whether a user is active to sign in or not. If the account
53
+ # is expired, it should never be allowed.
54
+ #
55
+ # @return [bool]
56
+ def active_for_authentication?
57
+ super && !self.expired?
58
+ end
59
+
60
+ # The message sym, if {#active_for_authentication?} returns +false+. E.g. needed
61
+ # for i18n.
62
+ def inactive_message
63
+ !self.expired? ? super : :expired
64
+ end
65
+
66
+ end
67
+
68
+ module ClassMethods
69
+ ::Devise::Models.config(self, :expire_after, :delete_expired_after)
70
+
71
+ # Sample method for daily cron to mark expired entries.
72
+ #
73
+ # @example You can overide this in your +resource+ model
74
+ # def self.mark_expired
75
+ # puts 'overwritten mark_expired'
76
+ # end
77
+ def mark_expired
78
+ all.each do |u|
79
+ u.expire! if u.expired? && u.expired_at.nil?
80
+ end
81
+ return
82
+ end
83
+
84
+ # Scope method to collect all expired users since +time+ ago
85
+ def expired_for(time = delete_expired_after)
86
+ where('expired_at < ?', time.ago)
87
+ end
88
+
89
+ # Sample method for daily cron to delete all expired entries after a
90
+ # given amount of +time+.
91
+ #
92
+ # In your overwritten method you can "blank out" the object instead of
93
+ # deleting it.
94
+ #
95
+ # *Word of warning*: You have to handle the dependent method
96
+ # on the +resource+ relations (+:destroy+ or +:nullify+) and catch this
97
+ # behavior (see http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Deleting+from+associations).
98
+ #
99
+ # @example
100
+ # Resource.delete_all_expired_for 90.days
101
+ # @example You can overide this in your +resource+ model
102
+ # def self.delete_all_expired_for(time = 90.days)
103
+ # puts 'overwritten delete call'
104
+ # end
105
+ # @example Overwritten version to blank out the object.
106
+ # def self.delete_all_expired_for(time = 90.days)
107
+ # expired_for(time).each do |u|
108
+ # u.update_attributes first_name: nil, last_name: nil
109
+ # end
110
+ # end
111
+ def delete_all_expired_for(time)
112
+ expired_for(time).delete_all
113
+ end
114
+
115
+ # Version of {#delete_all_expired_for} without arguments (uses
116
+ # configured +delete_expired_after+ default value).
117
+ # @see #delete_all_expired_for
118
+ def delete_all_expired
119
+ delete_all_expired_for(delete_expired_after)
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
@@ -26,8 +26,11 @@ module DeviseSecurityExtension
26
26
  " # captcha integration for sign in form\n" +
27
27
  " # config.captcha_for_sign_in = true\n\n" +
28
28
  " # captcha integration for unlock form\n" +
29
- " # config.captcha_for_unlock = true" +
30
- "\n", :before => /end[ |\n|]+\Z/
29
+ " # config.captcha_for_unlock = true\n\n" +
30
+ " # ==> Configuration for :expirable\n" +
31
+ " # Time period for account expiry from last_activity_at\n" +
32
+ " config.expire_after = 90.days\n" +
33
+ "", :before => /end[ |\n|]+\Z/
31
34
  end
32
35
 
33
36
  def copy_locale
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.5.1
4
+ version: 0.6.0
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: 2011-12-27 00:00:00.000000000 Z
13
+ date: 2011-12-28 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails
17
- requirement: &16685220 !ruby/object:Gem::Requirement
17
+ requirement: &21216320 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: 3.1.1
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *16685220
25
+ version_requirements: *21216320
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: devise
28
- requirement: &16683580 !ruby/object:Gem::Requirement
28
+ requirement: &21234920 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *16683580
36
+ version_requirements: *21234920
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: rails_email_validator
39
- requirement: &16682360 !ruby/object:Gem::Requirement
39
+ requirement: &21250840 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: '0'
45
45
  type: :development
46
46
  prerelease: false
47
- version_requirements: *16682360
47
+ version_requirements: *21250840
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: easy_captcha
50
- requirement: &16681140 !ruby/object:Gem::Requirement
50
+ requirement: &21246220 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,10 +55,10 @@ dependencies:
55
55
  version: '0'
56
56
  type: :development
57
57
  prerelease: false
58
- version_requirements: *16681140
58
+ version_requirements: *21246220
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: bundler
61
- requirement: &16696860 !ruby/object:Gem::Requirement
61
+ requirement: &21243800 !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
64
64
  - - ~>
@@ -66,10 +66,10 @@ dependencies:
66
66
  version: 1.0.0
67
67
  type: :development
68
68
  prerelease: false
69
- version_requirements: *16696860
69
+ version_requirements: *21243800
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: jeweler
72
- requirement: &16692820 !ruby/object:Gem::Requirement
72
+ requirement: &21268580 !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
75
  - - ~>
@@ -77,7 +77,7 @@ dependencies:
77
77
  version: 1.5.2
78
78
  type: :development
79
79
  prerelease: false
80
- version_requirements: *16692820
80
+ version_requirements: *21268580
81
81
  description: An enterprise security extension for devise, trying to meet industrial
82
82
  standard security demands for web applications.
83
83
  email: team@phatworx.de
@@ -101,8 +101,10 @@ files:
101
101
  - devise_security_extension.gemspec
102
102
  - lib/devise_security_extension.rb
103
103
  - lib/devise_security_extension/controllers/helpers.rb
104
+ - lib/devise_security_extension/hooks/expirable.rb
104
105
  - lib/devise_security_extension/hooks/password_expirable.rb
105
106
  - lib/devise_security_extension/hooks/session_limitable.rb
107
+ - lib/devise_security_extension/models/expirable.rb
106
108
  - lib/devise_security_extension/models/old_password.rb
107
109
  - lib/devise_security_extension/models/password_archivable.rb
108
110
  - lib/devise_security_extension/models/password_expirable.rb
@@ -132,7 +134,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
132
134
  version: '0'
133
135
  segments:
134
136
  - 0
135
- hash: 2266778624520241726
137
+ hash: -3314141216685045721
136
138
  required_rubygems_version: !ruby/object:Gem::Requirement
137
139
  none: false
138
140
  requirements: