Home > Software design >  Displaying failure messages using Devise gem in Rails
Displaying failure messages using Devise gem in Rails

Time:10-12

Hello
I have a problem with displaying Devise failure messages. No matter what I do, I always get the "invalid" message even though the account is locked. My goal is to display the "locked" message for 10 minutes after 5 failed attempts.

The gem is configured properly because accounts are being locked correctly. The only problem I have is with the messages.

This is my code from the devise.rb file, which is related to the lockable module:

  config.paranoid = false
  config.lock_strategy = :failed_attempts
  config.unlock_keys = [:time]
  config.unlock_strategy = :time
  config.maximum_attempts = 5
  config.unlock_in = 10.minutes
  config.last_attempt_warning = true

I found other topics on stackoverflow (e.g. Some devise messages are not shown, Devise: lockable - last_attempt_warning not displaying), where people say it's because of the paranoid mode, that's why I disabled it, but it still doesn't solve my issue. Devise does not seem to display any other message than "invalid" no matter what I put in the Devise config file (last_attempt_warning isn't showing up as well).

This is part of devise.en.yml related to failures:

en:  
  devise:
   failure:
    already_authenticated: "You are already logged in."
    deactivated: "Your account is no longer active. Please contact your administrator for access."
    inactive: "Your account is not activated yet."
    invalid: "Sorry, the email or password you entered is incorrect."
    last_attempt: "You have one more attempt before your account will be locked."
    locked: "Your account has been locked. Try to log in again in 5 minutes."
    not_found_in_database: "Sorry, the email or password you entered is incorrect."
    timeout: "Your session expired. Please log in again to continue."
    unauthenticated: "You need to log in or sign up before continuing."
    unconfirmed: "You have to confirm your account before continuing."

I tried to workaround it by creating a method in Sessions Controller:

before_action :check_failed_attempts, only: :create
def check_failed_attempts
  flash.clear

  email = params["educator"]["email"]
  return unless email

  user = Person.find_by(email: email)
  return unless user

  if user.access_locked?
    flash[:alert] = I18n.t "devise.failure.locked"
  end
end

but devise seems to override the flash[:alert] and displays the invalid message anyway.

I spent a few hours trying to fix it and run out of ideas already, so I appreciate any help.

CodePudding user response:

You are not halting the request cycle in your before_action, so the request is proceeding to call the create action which is overriding the flash[:alert]. From the documentation:

If a "before" filter renders or redirects, the action will not run. If there are additional filters scheduled to run after that filter, they are also cancelled.

def check_failed_attempts
  flash.clear

  email = params["educator"]["email"]
  return unless email

  user = Person.find_by(email: email)
  return unless user

  if user.access_locked?
    flash[:alert] = I18n.t "devise.failure.locked"
    redirect_to new_educator_session_path
  end
end
  • Related