diff --git a/app/models/user.rb b/app/models/user.rb index 633610d9d..1c9ace227 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -57,6 +57,8 @@ before_validation :clean_document_number + before_create :set_password_changed_at + # Get the existing user by email if the provider gives us a verified email. def self.first_or_initialize_for_oauth(auth) oauth_email = auth.info.email @@ -240,6 +242,10 @@ true end + def set_password_changed_at + set_password_changed_at = created_at + end + def ability @ability ||= Ability.new(self) end diff --git a/config/initializers/devise_security_extension.rb b/config/initializers/devise_security_extension.rb index 83b88200e..b38393b75 100644 --- a/config/initializers/devise_security_extension.rb +++ b/config/initializers/devise_security_extension.rb @@ -10,7 +10,7 @@ Devise.setup do |config| # config.password_regex = /(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])/ # How many passwords to keep in archive - # config.password_archiving_count = 5 + #config.password_archiving_count = 5 # Deny old password (true, false, count) # config.deny_old_passwords = true @@ -18,7 +18,6 @@ Devise.setup do |config| # enable email validation for :secure_validatable. (true, false, validation_options) # dependency: need an email validator like rails_email_validator # config.email_validation = true - # captcha integration for recover form # config.captcha_for_recover = true @@ -42,20 +41,22 @@ module Devise module Models module PasswordExpirable def need_change_password? - if self.administrator? - #is administrator - if self.expire_password_after.is_a? Fixnum or self.expire_password_after.is_a? Float - self.password_changed_at.nil? or self.password_changed_at < self.expire_password_after.ago - else - #not change password - false - end - else - #It is not an administrator - false + if password_change? + password_expired? + else + false end end - end + + def password_change? + self.administrator? && password_expired? + end + + def password_expired? + self.password_changed_at < self.expire_password_after.ago + end + + end #module PasswordExpirable module SecureValidatable def self.included(base) @@ -63,24 +64,11 @@ module Devise assert_secure_validations_api!(base) base.class_eval do - # validate login in a strict way if not yet validated - unless devise_validation_enabled? - validates :email, :presence => true, :if => :email_required? - validates :email, :uniqueness => true, :allow_blank => true, :if => :email_changed? # check uniq for email ever - validates :password, :presence => true, :length => password_length, :confirmation => true, :if => :password_required? - end - - # extra validations - #validates :password, :format => { :with => password_regex, :message => :password_format }, :if => :password_required? - # don't allow use same password + validate :current_equal_password_validation end end - def self.assert_secure_validations_api!(base) - raise "Could not use SecureValidatable on #{base}" unless base.respond_to?(:validates) - end - def current_equal_password_validation if !self.new_record? && !self.encrypted_password_change.nil? && !self.erased? dummy = self.class.new @@ -90,38 +78,7 @@ module Devise end end - protected + end #module SecureValidatable - # Checks whether a password is needed or not. For validations only. - # Passwords are always required if it's a new record, or if the password - # or confirmation are being set somewhere. - def password_required? - !persisted? || !password.nil? || !password_confirmation.nil? - end - - def email_required? - true - end - - module ClassMethods - Devise::Models.config(self, :password_regex, :password_length, :email_validation) - - private - def has_uniqueness_validation_of_login? - validators.any? do |validator| - validator.kind_of?(ActiveRecord::Validations::UniquenessValidator) && - validator.attributes.include?(login_attribute) - end - end - - def login_attribute - authentication_keys[0] - end - - def devise_validation_enabled? - self.ancestors.map(&:to_s).include? 'Devise::Models::Validatable' - end - end - end - end -end \ No newline at end of file + end #module Models +end #module Devise \ No newline at end of file diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml index f031d62b5..29bc0a620 100755 --- a/config/locales/devise.en.yml +++ b/config/locales/devise.en.yml @@ -4,7 +4,7 @@ en: devise: password_expired: expire_password: "Password expired" - change_required: "Your password has expired" + change_required: "Your password is expired" change_password: "Change your password" new_password: "New password" updated: "Password successfully updated" diff --git a/config/locales/devise.security_extension.de.yml b/config/locales/devise.security_extension.de.yml deleted file mode 100644 index cad39d9b7..000000000 --- a/config/locales/devise.security_extension.de.yml +++ /dev/null @@ -1,16 +0,0 @@ -de: - errors: - messages: - taken_in_past: "wurde bereits in der Vergangenheit verwendet!" - equal_to_current_password: "darf nicht dem aktuellen Passwort entsprechen!" - password_format: "müssen große, kleine Buchstaben und Ziffern enthalten" - devise: - invalid_captcha: "Die Captchaeingabe ist nicht gültig!" - paranoid_verify: - code_required: "Bitte geben Sie den Code unser Support-Team zur Verfügung gestellt" - password_expired: - updated: "Das neue Passwort wurde übernommen." - change_required: "Ihr Passwort ist abgelaufen. Bitte vergeben sie ein neues Passwort!" - failure: - session_limited: 'Ihre Anmeldedaten wurden in einem anderen Browser genutzt. Bitte melden Sie sich erneut an, um in diesem Browser fortzufahren.' - expired: 'Ihr Account ist aufgrund zu langer Inaktiviät abgelaufen. Bitte kontaktieren Sie den Administrator.' diff --git a/config/locales/devise.security_extension.en.yml b/config/locales/devise.security_extension.en.yml deleted file mode 100644 index e73d6e245..000000000 --- a/config/locales/devise.security_extension.en.yml +++ /dev/null @@ -1,16 +0,0 @@ -en: - errors: - messages: - taken_in_past: "was used previously." - equal_to_current_password: "must be different than the current password." - password_format: "must contain big, small letters and digits" - devise: - invalid_captcha: "The captcha input was invalid." - paranoid_verify: - code_required: "Please enter the code our support team provided" - password_expired: - updated: "Your new password is saved." - change_required: "Your password is expired. Please renew your password." - failure: - session_limited: 'Your login credentials were used in another browser. Please sign in again to continue in this browser.' - expired: 'Your account has expired due to inactivity. Please contact the site administrator.' diff --git a/config/locales/devise.security_extension.it.yml b/config/locales/devise.security_extension.it.yml deleted file mode 100644 index 646ae4ea0..000000000 --- a/config/locales/devise.security_extension.it.yml +++ /dev/null @@ -1,10 +0,0 @@ -it: - errors: - messages: - taken_in_past: "e' stata gia' utilizzata in passato!" - equal_to_current_password: " deve essere differente dalla password corrente!" - devise: - invalid_captcha: "Il captcha inserito non e' valido!" - password_expired: - updated: "La tua nuova password e' stata salvata." - change_required: "La tua password e' scaduta. Si prega di rinnovarla!" \ No newline at end of file diff --git a/lib/tasks/users.rake b/lib/tasks/users.rake index efbeeaa94..98fcae5d2 100644 --- a/lib/tasks/users.rake +++ b/lib/tasks/users.rake @@ -76,4 +76,12 @@ namespace :users do task remove_erased_identities: :environment do Identity.joins(:user).where('users.erased_at IS NOT NULL').destroy_all end + + desc "Update password changed at for existing users" + task update_password_changed_at: :environment do + User.all.each do |user| + user.update(password_changed_at:user.created_at) + end + end + end diff --git a/spec/features/users_auth_spec.rb b/spec/features/users_auth_spec.rb index 1b365f16d..f16772fd4 100644 --- a/spec/features/users_auth_spec.rb +++ b/spec/features/users_auth_spec.rb @@ -322,4 +322,19 @@ feature 'Users' do expect(page).to_not have_content "Your password is expired" end + scenario 'Admin with password expired trying to use same password' do + user = create(:user, password_changed_at: Time.now - 1.year, password: '123456789') + admin = create(:administrator, user: user) + login_as(admin.user) + visit root_path + expect(page).to have_content "Your password is expired" + fill_in 'user_current_password', with: 'judgmentday' + fill_in 'user_password', with: '123456789' + fill_in 'user_password_confirmation', with: '123456789' + click_button 'Change your password' + expect(page).to have_content "must be different than the current password." + #expect(page).to have_content "You can not use the same password. Please choose another one." + end + + end