Enable devise lockable module with default values
In order to the display a warn text on the last attempt before the account is locked, we need update config.paranoid to false as the devise documentation explains. Adding "config.paranoid: false" implies further changes to the code, so for now we unncomment the default value "config.last_attempt_warning = true" and update it to false.
This commit is contained in:
@@ -3,7 +3,7 @@ class User < ApplicationRecord
|
||||
attribute :registering_from_web, default: false
|
||||
|
||||
devise :database_authenticatable, :registerable, :confirmable, :recoverable, :rememberable,
|
||||
:trackable, :validatable, :omniauthable, :password_expirable, :secure_validatable,
|
||||
:trackable, :validatable, :omniauthable, :password_expirable, :secure_validatable, :lockable,
|
||||
authentication_keys: [:login]
|
||||
|
||||
acts_as_voter
|
||||
|
||||
@@ -167,27 +167,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 = 20
|
||||
|
||||
# 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 = false
|
||||
|
||||
# ==> Configuration for :recoverable
|
||||
#
|
||||
|
||||
11
db/migrate/20231009073912_add_lockable_to_devise.rb
Normal file
11
db/migrate/20231009073912_add_lockable_to_devise.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
class AddLockableToDevise < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
# Only if lock strategy is :failed_attempts
|
||||
add_column :users, :failed_attempts, :integer, default: 0, null: false
|
||||
add_column :users, :locked_at, :datetime
|
||||
|
||||
# Add these only if unlock strategy is :email or :both
|
||||
add_column :users, :unlock_token, :string
|
||||
add_index :users, :unlock_token, unique: true
|
||||
end
|
||||
end
|
||||
@@ -1644,6 +1644,9 @@ ActiveRecord::Schema.define(version: 2023_10_12_141318) do
|
||||
t.boolean "recommended_debates", default: true
|
||||
t.boolean "recommended_proposals", default: true
|
||||
t.string "subscriptions_token"
|
||||
t.integer "failed_attempts", default: 0, null: false
|
||||
t.datetime "locked_at"
|
||||
t.string "unlock_token"
|
||||
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
|
||||
t.index ["date_of_birth"], name: "index_users_on_date_of_birth"
|
||||
t.index ["email"], name: "index_users_on_email", unique: true
|
||||
@@ -1652,6 +1655,7 @@ ActiveRecord::Schema.define(version: 2023_10_12_141318) do
|
||||
t.index ["hidden_at"], name: "index_users_on_hidden_at"
|
||||
t.index ["password_changed_at"], name: "index_users_on_password_changed_at"
|
||||
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
|
||||
t.index ["username"], name: "index_users_on_username"
|
||||
end
|
||||
|
||||
|
||||
25
spec/controllers/users/sessions_controller_spec.rb
Normal file
25
spec/controllers/users/sessions_controller_spec.rb
Normal file
@@ -0,0 +1,25 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe Users::SessionsController do
|
||||
before { request.env["devise.mapping"] = Devise.mappings[:user] }
|
||||
|
||||
let!(:user) { create(:user, email: "citizen@consul.org", password: "12345678") }
|
||||
|
||||
describe "Devise lock" do
|
||||
context "when devise sign in maximum_attempts reached", :with_frozen_time do
|
||||
it "locks the user account and sends an email to the account with an unlock link" do
|
||||
user.update(failed_attempts: 19)
|
||||
|
||||
expect do
|
||||
post :create, params: { user: { login: "citizen@consul.org", password: "wrongpassword" }}
|
||||
end.to change { user.reload.failed_attempts }.by(1)
|
||||
.and change { user.reload.locked_at }.from(nil).to(Time.current)
|
||||
|
||||
expect(ActionMailer::Base.deliveries.count).to eq(1)
|
||||
body = ActionMailer::Base.deliveries.last.body
|
||||
expect(body).to have_content "Your account has been locked"
|
||||
expect(body).to have_link "Unlock my account"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user