From 8d03a6747c069a3ab38e6815e410f1869a60509f Mon Sep 17 00:00:00 2001 From: pedong Date: Wed, 22 May 2019 18:33:00 +0200 Subject: [PATCH 1/4] add lockable to User, Gestionnaire, administration, Administrateur --- app/models/administrateur.rb | 2 +- app/models/administration.rb | 2 +- app/models/gestionnaire.rb | 2 +- app/models/user.rb | 2 +- config/initializers/devise.rb | 12 +++++----- .../20190522131959_add_lockable_to_devise.rb | 23 +++++++++++++++++++ 6 files changed, 33 insertions(+), 10 deletions(-) create mode 100644 db/migrate/20190522131959_add_lockable_to_devise.rb diff --git a/app/models/administrateur.rb b/app/models/administrateur.rb index 87c4ed221..fbbe9fafb 100644 --- a/app/models/administrateur.rb +++ b/app/models/administrateur.rb @@ -4,7 +4,7 @@ class Administrateur < ApplicationRecord include ActiveRecord::SecureToken devise :database_authenticatable, :registerable, :async, - :recoverable, :rememberable, :trackable, :validatable + :recoverable, :rememberable, :trackable, :validatable, :lockable has_and_belongs_to_many :gestionnaires has_many :administrateurs_procedures diff --git a/app/models/administration.rb b/app/models/administration.rb index 8d98bab4d..0fdf004d4 100644 --- a/app/models/administration.rb +++ b/app/models/administration.rb @@ -1,7 +1,7 @@ class Administration < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable - devise :database_authenticatable, :rememberable, :trackable, :validatable, :omniauthable, :async, omniauth_providers: [:github] + devise :database_authenticatable, :rememberable, :trackable, :validatable, :omniauthable, :lockable, :async, omniauth_providers: [:github] def self.from_omniauth(params) find_by(email: params["info"]["email"]) diff --git a/app/models/gestionnaire.rb b/app/models/gestionnaire.rb index c5ab8b7c2..fa2a0e669 100644 --- a/app/models/gestionnaire.rb +++ b/app/models/gestionnaire.rb @@ -3,7 +3,7 @@ class Gestionnaire < ApplicationRecord include EmailSanitizableConcern devise :database_authenticatable, :registerable, :async, - :recoverable, :rememberable, :trackable, :validatable + :recoverable, :rememberable, :trackable, :validatable, :lockable has_and_belongs_to_many :administrateurs diff --git a/app/models/user.rb b/app/models/user.rb index c676fb159..598eeed13 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -10,7 +10,7 @@ class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :async, - :recoverable, :rememberable, :trackable, :validatable, :confirmable + :recoverable, :rememberable, :trackable, :validatable, :confirmable, :lockable has_many :dossiers, dependent: :destroy has_many :invites, dependent: :destroy diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 4b74c2e52..6f33cc6a6 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -161,27 +161,27 @@ Devise.setup do |config| # Defines which strategy will be used to lock an account. # :failed_attempts = Locks an account after a number of failed attempts to sign in. # :none = No lock strategy. You should handle locking by yourself. - # config.lock_strategy = :failed_attempts + config.lock_strategy = :failed_attempts # Defines which key will be used when locking and unlocking an account - # config.unlock_keys = [ :email ] + config.unlock_keys = [ :email ] # Defines which strategy will be used to unlock an account. # :email = Sends an unlock link to the user email # :time = Re-enables login after a certain amount of time (see :unlock_in below) # :both = Enables both strategies # :none = No unlock strategy. You should handle unlocking by yourself. - # config.unlock_strategy = :both + config.unlock_strategy = :both # Number of authentication tries before locking an account if lock_strategy # is failed attempts. - # config.maximum_attempts = 20 + config.maximum_attempts = 6 # Time interval to unlock the account if :time is enabled as unlock_strategy. - # config.unlock_in = 1.hour + config.unlock_in = 1.hour # Warn on the last attempt before the account is locked. - # config.last_attempt_warning = true + config.last_attempt_warning = true # ==> Configuration for :recoverable # diff --git a/db/migrate/20190522131959_add_lockable_to_devise.rb b/db/migrate/20190522131959_add_lockable_to_devise.rb new file mode 100644 index 000000000..c83dc6696 --- /dev/null +++ b/db/migrate/20190522131959_add_lockable_to_devise.rb @@ -0,0 +1,23 @@ +class AddLockableToDevise < ActiveRecord::Migration[5.2] + def change + add_column :users, :failed_attempts, :integer, default: 0, null: false + add_column :users, :unlock_token, :string + add_column :users, :locked_at, :datetime + add_index :users, :unlock_token, unique: true + + add_column :gestionnaires, :failed_attempts, :integer, default: 0, null: false + add_column :gestionnaires, :unlock_token, :string + add_column :gestionnaires, :locked_at, :datetime + add_index :gestionnaires, :unlock_token, unique: true + + add_column :administrateurs, :failed_attempts, :integer, default: 0, null: false + add_column :administrateurs, :unlock_token, :string + add_column :administrateurs, :locked_at, :datetime + add_index :administrateurs, :unlock_token, unique: true + + add_column :administrations, :failed_attempts, :integer, default: 0, null: false + add_column :administrations, :unlock_token, :string + add_column :administrations, :locked_at, :datetime + add_index :administrations, :unlock_token, unique: true + end +end From 0ed9c4cbd462a8023f924124abc9594c9f7aea2d Mon Sep 17 00:00:00 2001 From: pedong Date: Tue, 25 Jun 2019 15:02:50 +0200 Subject: [PATCH 2/4] add check access_locked? when login --- app/controllers/users/sessions_controller.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb index 783043bcf..733664a53 100644 --- a/app/controllers/users/sessions_controller.rb +++ b/app/controllers/users/sessions_controller.rb @@ -103,10 +103,12 @@ class Users::SessionsController < Sessions::SessionsController resource = klass.find_for_database_authentication(email: params[:user][:email]) if resource.present? - if resource.valid_password?(params[:user][:password]) - resource.remember_me = remember_me - sign_in resource - resource.force_sync_credentials + if resource.access_locked? + if resource.valid_password?(params[:user][:password]) + resource.remember_me = remember_me + sign_in resource + resource.force_sync_credentials + end end end end From 9438f962c59441cf0657f0e12360418698f64a45 Mon Sep 17 00:00:00 2001 From: pedong Date: Tue, 25 Jun 2019 18:00:13 +0200 Subject: [PATCH 3/4] add alert for account is locked --- app/controllers/users/sessions_controller.rb | 26 +++++++++++++------- config/initializers/devise.rb | 2 +- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/app/controllers/users/sessions_controller.rb b/app/controllers/users/sessions_controller.rb index 733664a53..cb11a5045 100644 --- a/app/controllers/users/sessions_controller.rb +++ b/app/controllers/users/sessions_controller.rb @@ -15,9 +15,14 @@ class Users::SessionsController < Sessions::SessionsController # POST /resource/sign_in def create remember_me = params[:user][:remember_me] == '1' - try_to_authenticate(User, remember_me) - try_to_authenticate(Gestionnaire, remember_me) - try_to_authenticate(Administrateur, remember_me) + + if resource_locked?(try_to_authenticate(User, remember_me)) || + resource_locked?(try_to_authenticate(Gestionnaire, remember_me)) || + resource_locked?(try_to_authenticate(Administrateur, remember_me)) + flash.alert = 'Votre compte est verrouillé.' + new + return render :new, status: 401 + end if user_signed_in? current_user.update(loged_in_with_france_connect: nil) @@ -103,13 +108,16 @@ class Users::SessionsController < Sessions::SessionsController resource = klass.find_for_database_authentication(email: params[:user][:email]) if resource.present? - if resource.access_locked? - if resource.valid_password?(params[:user][:password]) - resource.remember_me = remember_me - sign_in resource - resource.force_sync_credentials - end + if resource.valid_password?(params[:user][:password]) + resource.remember_me = remember_me + sign_in resource + resource.force_sync_credentials end end + resource + end + + def resource_locked?(resource) + resource.present? && resource.access_locked? end end diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 6f33cc6a6..4cbd343d9 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -164,7 +164,7 @@ Devise.setup do |config| config.lock_strategy = :failed_attempts # Defines which key will be used when locking and unlocking an account - config.unlock_keys = [ :email ] + config.unlock_keys = [:email] # Defines which strategy will be used to unlock an account. # :email = Sends an unlock link to the user email From 5921da9397056547349a84391d44c708f419febf Mon Sep 17 00:00:00 2001 From: pedong Date: Mon, 29 Jul 2019 16:30:04 +0200 Subject: [PATCH 4/4] add schema.rb updated --- db/schema.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/db/schema.rb b/db/schema.rb index a4ef748da..a6dc86588 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -63,8 +63,12 @@ ActiveRecord::Schema.define(version: 2019_07_17_151228) do t.boolean "active", default: false t.jsonb "features", default: {}, null: false t.string "encrypted_token" + t.integer "failed_attempts", default: 0, null: false + t.string "unlock_token" + t.datetime "locked_at" t.index ["email"], name: "index_administrateurs_on_email", unique: true t.index ["reset_password_token"], name: "index_administrateurs_on_reset_password_token", unique: true + t.index ["unlock_token"], name: "index_administrateurs_on_unlock_token", unique: true end create_table "administrateurs_gestionnaires", id: false, force: :cascade do |t| @@ -100,8 +104,12 @@ ActiveRecord::Schema.define(version: 2019_07_17_151228) do t.string "last_sign_in_ip" t.datetime "created_at" t.datetime "updated_at" + t.integer "failed_attempts", default: 0, null: false + t.string "unlock_token" + t.datetime "locked_at" t.index ["email"], name: "index_administrations_on_email", unique: true t.index ["reset_password_token"], name: "index_administrations_on_reset_password_token", unique: true + t.index ["unlock_token"], name: "index_administrations_on_unlock_token", unique: true end create_table "assign_tos", id: :serial, force: :cascade do |t| @@ -399,8 +407,12 @@ ActiveRecord::Schema.define(version: 2019_07_17_151228) do t.text "encrypted_login_token" t.datetime "login_token_created_at" t.jsonb "features", default: {"enable_email_login_token"=>true}, null: false + t.integer "failed_attempts", default: 0, null: false + t.string "unlock_token" + t.datetime "locked_at" t.index ["email"], name: "index_gestionnaires_on_email", unique: true t.index ["reset_password_token"], name: "index_gestionnaires_on_reset_password_token", unique: true + t.index ["unlock_token"], name: "index_gestionnaires_on_unlock_token", unique: true end create_table "individuals", id: :serial, force: :cascade do |t| @@ -605,10 +617,14 @@ ActiveRecord::Schema.define(version: 2019_07_17_151228) do t.string "confirmation_token" t.datetime "confirmed_at" t.datetime "confirmation_sent_at" + t.integer "failed_attempts", default: 0, null: false + t.string "unlock_token" + t.datetime "locked_at" t.text "unconfirmed_email" t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["email"], name: "index_users_on_email", unique: true t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true + t.index ["unlock_token"], name: "index_users_on_unlock_token", unique: true end create_table "virus_scans", force: :cascade do |t|