From 8d883b1e1701438218abf62f286a2907e92b5051 Mon Sep 17 00:00:00 2001
From: Marcia
Date: Thu, 15 Sep 2016 11:45:03 +0200
Subject: [PATCH 1/7] mejoras de codigo
---
Gemfile | 1 +
Gemfile.lock | 4 +
app/models/user.rb | 4 +-
.../devise/password_expired/show.html.erb | 14 ++
config/i18n-tasks.yml | 1 +
.../initializers/devise_security_extension.rb | 127 ++++++++++++++++++
config/locales/activerecord.en.yml | 1 +
config/locales/activerecord.es.yml | 1 +
config/locales/devise.en.yml | 7 +
config/locales/devise.es.yml | 7 +
.../locales/devise.security_extension.de.yml | 16 +++
.../locales/devise.security_extension.en.yml | 16 +++
.../locales/devise.security_extension.it.yml | 10 ++
.../20160901104320_add_password_expired.rb | 6 +
.../20160901104320_add_password_expired.rb~ | 4 +
db/schema.rb | 4 +-
spec/features/users_auth_spec.rb | 37 +++++
17 files changed, 257 insertions(+), 3 deletions(-)
create mode 100644 app/views/devise/password_expired/show.html.erb
create mode 100644 config/initializers/devise_security_extension.rb
create mode 100644 config/locales/devise.security_extension.de.yml
create mode 100644 config/locales/devise.security_extension.en.yml
create mode 100644 config/locales/devise.security_extension.it.yml
create mode 100644 db/migrate/20160901104320_add_password_expired.rb
create mode 100644 db/migrate/20160901104320_add_password_expired.rb~
diff --git a/Gemfile b/Gemfile
index 3f3119770..9d7499d82 100644
--- a/Gemfile
+++ b/Gemfile
@@ -20,6 +20,7 @@ gem 'jquery-ui-rails'
gem 'turbolinks'
gem 'devise', '~> 3.5.7'
+gem 'devise_security_extension'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'
gem 'omniauth'
diff --git a/Gemfile.lock b/Gemfile.lock
index 103ec214d..e918a9648 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -138,6 +138,9 @@ GEM
warden (~> 1.2.3)
devise-async (0.10.2)
devise (>= 3.2, < 4.0)
+ devise_security_extension (0.10.0)
+ devise (>= 3.0.0, < 4.0)
+ railties (>= 3.2.6, < 5.0)
diff-lcs (1.2.5)
docile (1.1.5)
easy_translate (0.5.0)
@@ -460,6 +463,7 @@ DEPENDENCIES
delayed_job_active_record (~> 4.1.0)
devise (~> 3.5.7)
devise-async
+ devise_security_extension
email_spec
factory_girl_rails
faker
diff --git a/app/models/user.rb b/app/models/user.rb
index 60bc2364a..633610d9d 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,8 +1,8 @@
-class User < ActiveRecord::Base
+ class User < ActiveRecord::Base
include Verification
- devise :database_authenticatable, :registerable, :confirmable,
+ devise :password_expirable, :secure_validatable, :database_authenticatable, :registerable, :confirmable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, :async
acts_as_voter
diff --git a/app/views/devise/password_expired/show.html.erb b/app/views/devise/password_expired/show.html.erb
new file mode 100644
index 000000000..0c750dd1e
--- /dev/null
+++ b/app/views/devise/password_expired/show.html.erb
@@ -0,0 +1,14 @@
+<%= t("devise.password_expired.expire_password") %>
+
+<%= form_for(resource, :as => resource_name, :url => [resource_name, :password_expired], :html => { :method => :put }) do |f| %>
+ <%= devise_error_messages! %>
+
+ <%= f.password_field :current_password %>
+
+ <%= f.label t("devise.password_expired.new_password") %>
+ <%= f.password_field :password, label: false %>
+
+ <%= f.password_field :password_confirmation %>
+
+ <%= f.submit t("devise.password_expired.change_password") %>
+<% end %>
\ No newline at end of file
diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml
index 250ed18f9..9cf9f8137 100644
--- a/config/i18n-tasks.yml
+++ b/config/i18n-tasks.yml
@@ -101,6 +101,7 @@ ignore_missing:
- 'errors.messages.taken'
- 'devise.failure.invalid'
- 'devise.registrations.destroyed'
+ - 'devise.password_expired.*'
## Consider these keys used:
ignore_unused:
diff --git a/config/initializers/devise_security_extension.rb b/config/initializers/devise_security_extension.rb
new file mode 100644
index 000000000..83b88200e
--- /dev/null
+++ b/config/initializers/devise_security_extension.rb
@@ -0,0 +1,127 @@
+Devise.setup do |config|
+ # ==> Security Extension
+ # Configure security extension for devise
+
+ # Should the password expire (e.g 3.months)
+ # config.expire_password_after = false
+ config.expire_password_after = 1.year
+
+ # Need 1 char of A-Z, a-z and 0-9
+ # config.password_regex = /(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])/
+
+ # How many passwords to keep in archive
+ # config.password_archiving_count = 5
+
+ # Deny old password (true, false, count)
+ # config.deny_old_passwords = true
+
+ # 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
+
+ # captcha integration for sign up form
+ # config.captcha_for_sign_up = true
+
+ # captcha integration for sign in form
+ # config.captcha_for_sign_in = true
+
+ # captcha integration for unlock form
+ # config.captcha_for_unlock = true
+
+ # captcha integration for confirmation form
+ # config.captcha_for_confirmation = true
+
+ # Time period for account expiry from last_activity_at
+ # config.expire_after = 90.days
+end
+
+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
+ end
+ end
+ end
+
+ module SecureValidatable
+ def self.included(base)
+ base.extend ClassMethods
+ 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
+ dummy.encrypted_password = self.encrypted_password_change.first
+ dummy.password_salt = self.password_salt_change.first if self.respond_to? :password_salt_change and not self.password_salt_change.nil?
+ self.errors.add(:password, :equal_to_current_password) if dummy.valid_password?(self.password)
+ end
+ end
+
+ protected
+
+ # 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
diff --git a/config/locales/activerecord.en.yml b/config/locales/activerecord.en.yml
index 07791e53c..7de5b340e 100644
--- a/config/locales/activerecord.en.yml
+++ b/config/locales/activerecord.en.yml
@@ -54,6 +54,7 @@ en:
username: "Username"
password_confirmation: "Password confirmation"
password: "Password"
+ current_password: "Current password"
phone_number: "Phone number"
official_position: "Official position"
official_level: "Official level"
diff --git a/config/locales/activerecord.es.yml b/config/locales/activerecord.es.yml
index d5b7f0005..4dae4cb56 100644
--- a/config/locales/activerecord.es.yml
+++ b/config/locales/activerecord.es.yml
@@ -54,6 +54,7 @@ es:
username: "Nombre de usuario"
password_confirmation: "Confirmación de contraseña"
password: "Contraseña"
+ current_password: "Contraseña actual"
phone_number: "Teléfono"
official_position: "Cargo público"
official_level: "Nivel del cargo"
diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml
index 30fb488ce..f031d62b5 100755
--- a/config/locales/devise.en.yml
+++ b/config/locales/devise.en.yml
@@ -2,6 +2,12 @@
en:
devise:
+ password_expired:
+ expire_password: "Password expired"
+ change_required: "Your password has expired"
+ change_password: "Change your password"
+ new_password: "New password"
+ updated: "Password successfully updated"
confirmations:
confirmed: "Your account has been confirmed."
send_instructions: "In a few minutes you will receive an email containing instructions on how to reset your password."
@@ -62,3 +68,4 @@ en:
not_saved:
one: "1 error prevented this %{resource} from being saved:"
other: "%{count} errors prevented this %{resource} from being saved:"
+ equal_to_current_password: "must be different than the current password."
diff --git a/config/locales/devise.es.yml b/config/locales/devise.es.yml
index 1a9c3a3b8..6ede31f7d 100644
--- a/config/locales/devise.es.yml
+++ b/config/locales/devise.es.yml
@@ -1,5 +1,11 @@
es:
devise:
+ password_expired:
+ expire_password: "Contraseña caducada"
+ change_required: "Tu contraseña ha caducado"
+ change_password: "Cambia tu contraseña"
+ new_password: "Nueva contraseña"
+ updated: "Contraseña actualizada con éxito"
confirmations:
confirmed: "Tu cuenta ha sido confirmada. Por favor autentifícate con tu red social o tu usuario y contraseña"
send_instructions: "Recibirás un correo electrónico en unos minutos con instrucciones sobre cómo restablecer tu contraseña."
@@ -60,3 +66,4 @@ es:
not_saved:
one: "1 error impidió que este %{resource} fuera guardado:"
other: "%{count} errores impidieron que este %{resource} fuera guardado:"
+ equal_to_current_password: "debe ser diferente a la contraseña actual"
diff --git a/config/locales/devise.security_extension.de.yml b/config/locales/devise.security_extension.de.yml
new file mode 100644
index 000000000..cad39d9b7
--- /dev/null
+++ b/config/locales/devise.security_extension.de.yml
@@ -0,0 +1,16 @@
+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
new file mode 100644
index 000000000..e73d6e245
--- /dev/null
+++ b/config/locales/devise.security_extension.en.yml
@@ -0,0 +1,16 @@
+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
new file mode 100644
index 000000000..646ae4ea0
--- /dev/null
+++ b/config/locales/devise.security_extension.it.yml
@@ -0,0 +1,10 @@
+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/db/migrate/20160901104320_add_password_expired.rb b/db/migrate/20160901104320_add_password_expired.rb
new file mode 100644
index 000000000..aa759dd61
--- /dev/null
+++ b/db/migrate/20160901104320_add_password_expired.rb
@@ -0,0 +1,6 @@
+class AddPasswordExpired < ActiveRecord::Migration
+ def change
+ add_column :users, :password_changed_at, :datetime
+ add_index :users, :password_changed_at
+ end
+end
diff --git a/db/migrate/20160901104320_add_password_expired.rb~ b/db/migrate/20160901104320_add_password_expired.rb~
new file mode 100644
index 000000000..ac3a48f49
--- /dev/null
+++ b/db/migrate/20160901104320_add_password_expired.rb~
@@ -0,0 +1,4 @@
+class AddPasswordExpired < ActiveRecord::Migration
+ def change
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index becde4f8a..339ce7675 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 20160803154011) do
+ActiveRecord::Schema.define(version: 20160901104320) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -464,12 +464,14 @@ ActiveRecord::Schema.define(version: 20160803154011) do
t.boolean "email_digest", default: true
t.boolean "email_on_direct_message", default: true
t.boolean "official_position_badge", default: false
+ t.datetime "password_changed_at"
end
add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["geozone_id"], name: "index_users_on_geozone_id", using: :btree
add_index "users", ["hidden_at"], name: "index_users_on_hidden_at", using: :btree
+ add_index "users", ["password_changed_at"], name: "index_users_on_password_changed_at", using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
add_index "users", ["username"], name: "index_users_on_username", using: :btree
diff --git a/spec/features/users_auth_spec.rb b/spec/features/users_auth_spec.rb
index 9e1e67ef9..573e34a27 100644
--- a/spec/features/users_auth_spec.rb
+++ b/spec/features/users_auth_spec.rb
@@ -285,4 +285,41 @@ feature 'Users' do
expect(page).to have_content "Your password has been changed successfully."
end
+
+ scenario 'Sign in, admin with password expired' do
+ user = create(:user, password_changed_at: Time.now - 1.year)
+ admin = create(:administrator, user: user)
+
+ login_as(admin.user)
+ visit root_path
+
+ expect(page).to have_content "Your password has 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 "Password successfully updated"
+ end
+
+ scenario 'Sign in, admin without password expired' do
+ user = create(:user, password_changed_at: Time.now - 360.days)
+ admin = create(:administrator, user: user)
+
+ login_as(admin.user)
+ visit root_path
+
+ expect(page).to_not have_content "Your password has expired"
+ end
+
+ scenario 'Sign in, user with password expired' do
+ user = create(:user, password_changed_at: Time.now - 1.year)
+
+ login_as(user)
+ visit root_path
+ expect(page).to_not have_content "Your password has expired"
+ end
+
end
From 48325589485207108aa5cc239da0b0b024fde32d Mon Sep 17 00:00:00 2001
From: Marcia
Date: Thu, 15 Sep 2016 12:21:25 +0200
Subject: [PATCH 2/7] modificado mensaje en el test
---
spec/features/users_auth_spec.rb | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/spec/features/users_auth_spec.rb b/spec/features/users_auth_spec.rb
index 573e34a27..c842e73bc 100644
--- a/spec/features/users_auth_spec.rb
+++ b/spec/features/users_auth_spec.rb
@@ -311,7 +311,7 @@ feature 'Users' do
login_as(admin.user)
visit root_path
- expect(page).to_not have_content "Your password has expired"
+ expect(page).to_not have_content "Your password is expired"
end
scenario 'Sign in, user with password expired' do
@@ -319,7 +319,7 @@ feature 'Users' do
login_as(user)
visit root_path
- expect(page).to_not have_content "Your password has expired"
+ expect(page).to_not have_content "Your password is expired"
end
end
From fa833f5a4a4a913d494907b35970ff6d8620f83a Mon Sep 17 00:00:00 2001
From: Marcia
Date: Thu, 15 Sep 2016 13:06:03 +0200
Subject: [PATCH 3/7] modificado otro mensaje en los test
---
spec/features/users_auth_spec.rb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/spec/features/users_auth_spec.rb b/spec/features/users_auth_spec.rb
index c842e73bc..1b365f16d 100644
--- a/spec/features/users_auth_spec.rb
+++ b/spec/features/users_auth_spec.rb
@@ -293,7 +293,7 @@ feature 'Users' do
login_as(admin.user)
visit root_path
- expect(page).to have_content "Your password has expired"
+ expect(page).to have_content "Your password is expired"
fill_in 'user_current_password', with: 'judgmentday'
fill_in 'user_password', with: '123456789'
From 78c6a30424df21f6743b8812ac7445a23d3594a3 Mon Sep 17 00:00:00 2001
From: Marcia
Date: Tue, 27 Sep 2016 13:07:06 +0200
Subject: [PATCH 4/7] optimize code
---
app/models/user.rb | 6 ++
.../initializers/devise_security_extension.rb | 81 +++++--------------
config/locales/devise.en.yml | 2 +-
.../locales/devise.security_extension.de.yml | 16 ----
.../locales/devise.security_extension.en.yml | 16 ----
.../locales/devise.security_extension.it.yml | 10 ---
lib/tasks/users.rake | 8 ++
spec/features/users_auth_spec.rb | 15 ++++
8 files changed, 49 insertions(+), 105 deletions(-)
delete mode 100644 config/locales/devise.security_extension.de.yml
delete mode 100644 config/locales/devise.security_extension.en.yml
delete mode 100644 config/locales/devise.security_extension.it.yml
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
From 1e87810593c37659a2b3d388a4c1760c175b0569 Mon Sep 17 00:00:00 2001
From: Marcia
Date: Thu, 29 Sep 2016 14:34:37 +0200
Subject: [PATCH 5/7] improves expired password view
---
app/models/user.rb | 4 ++--
app/views/devise/password_expired/show.html.erb | 1 -
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/app/models/user.rb b/app/models/user.rb
index 1c9ace227..75367dbe1 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -2,8 +2,8 @@
include Verification
- devise :password_expirable, :secure_validatable, :database_authenticatable, :registerable, :confirmable,
- :recoverable, :rememberable, :trackable, :validatable, :omniauthable, :async
+ devise :database_authenticatable, :registerable, :confirmable, :recoverable, :rememberable,
+ :trackable, :validatable, :omniauthable, :async, :password_expirable, :secure_validatable
acts_as_voter
acts_as_paranoid column: :hidden_at
diff --git a/app/views/devise/password_expired/show.html.erb b/app/views/devise/password_expired/show.html.erb
index 0c750dd1e..33dc82f71 100644
--- a/app/views/devise/password_expired/show.html.erb
+++ b/app/views/devise/password_expired/show.html.erb
@@ -1,7 +1,6 @@
<%= t("devise.password_expired.expire_password") %>
<%= form_for(resource, :as => resource_name, :url => [resource_name, :password_expired], :html => { :method => :put }) do |f| %>
- <%= devise_error_messages! %>
<%= f.password_field :current_password %>
From 1f72c5cc74ea1cfcb147e1bb58e5bf495a21af00 Mon Sep 17 00:00:00 2001
From: Marcia
Date: Fri, 30 Sep 2016 10:10:20 +0200
Subject: [PATCH 6/7] improves expired password view
---
config/initializers/devise_security_extension.rb | 13 ++++---------
db/migrate/20160901104320_add_password_expired.rb~ | 4 ----
spec/features/users_auth_spec.rb | 1 -
3 files changed, 4 insertions(+), 14 deletions(-)
delete mode 100644 db/migrate/20160901104320_add_password_expired.rb~
diff --git a/config/initializers/devise_security_extension.rb b/config/initializers/devise_security_extension.rb
index b38393b75..5b13fc905 100644
--- a/config/initializers/devise_security_extension.rb
+++ b/config/initializers/devise_security_extension.rb
@@ -55,16 +55,13 @@ module Devise
def password_expired?
self.password_changed_at < self.expire_password_after.ago
end
-
- end #module PasswordExpirable
+ end
module SecureValidatable
def self.included(base)
base.extend ClassMethods
assert_secure_validations_api!(base)
-
base.class_eval do
-
validate :current_equal_password_validation
end
end
@@ -77,8 +74,6 @@ module Devise
self.errors.add(:password, :equal_to_current_password) if dummy.valid_password?(self.password)
end
end
-
- end #module SecureValidatable
-
- end #module Models
-end #module Devise
\ No newline at end of file
+ end
+ end
+end
\ No newline at end of file
diff --git a/db/migrate/20160901104320_add_password_expired.rb~ b/db/migrate/20160901104320_add_password_expired.rb~
deleted file mode 100644
index ac3a48f49..000000000
--- a/db/migrate/20160901104320_add_password_expired.rb~
+++ /dev/null
@@ -1,4 +0,0 @@
-class AddPasswordExpired < ActiveRecord::Migration
- def change
- end
-end
diff --git a/spec/features/users_auth_spec.rb b/spec/features/users_auth_spec.rb
index f16772fd4..bd58eabe0 100644
--- a/spec/features/users_auth_spec.rb
+++ b/spec/features/users_auth_spec.rb
@@ -333,7 +333,6 @@ feature 'Users' do
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
From 680c0636edf554ee579212ed6ce9fd3d3530320f Mon Sep 17 00:00:00 2001
From: Marcia
Date: Thu, 6 Oct 2016 14:19:48 +0200
Subject: [PATCH 7/7] expired password last
---
app/models/user.rb | 8 +-------
config/initializers/devise_security_extension.rb | 10 +---------
lib/tasks/users.rake | 2 +-
spec/features/users_auth_spec.rb | 8 ++++++--
4 files changed, 9 insertions(+), 19 deletions(-)
diff --git a/app/models/user.rb b/app/models/user.rb
index 75367dbe1..916c3d0b9 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,4 +1,4 @@
- class User < ActiveRecord::Base
+class User < ActiveRecord::Base
include Verification
@@ -57,8 +57,6 @@
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
@@ -242,10 +240,6 @@
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 5b13fc905..6e691acbe 100644
--- a/config/initializers/devise_security_extension.rb
+++ b/config/initializers/devise_security_extension.rb
@@ -41,16 +41,8 @@ module Devise
module Models
module PasswordExpirable
def need_change_password?
- if password_change?
- password_expired?
- else
- false
- end
- end
-
- def password_change?
self.administrator? && password_expired?
- end
+ end
def password_expired?
self.password_changed_at < self.expire_password_after.ago
diff --git a/lib/tasks/users.rake b/lib/tasks/users.rake
index 98fcae5d2..ccb749f9a 100644
--- a/lib/tasks/users.rake
+++ b/lib/tasks/users.rake
@@ -80,7 +80,7 @@ namespace :users do
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)
+ user.update(password_changed_at: user.created_at)
end
end
diff --git a/spec/features/users_auth_spec.rb b/spec/features/users_auth_spec.rb
index bd58eabe0..5b3c157d7 100644
--- a/spec/features/users_auth_spec.rb
+++ b/spec/features/users_auth_spec.rb
@@ -319,21 +319,25 @@ feature 'Users' do
login_as(user)
visit root_path
+
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
+ 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."
end
-
end