Allow define maximum_attemps and unlock_in

This commit is contained in:
taitus
2023-10-09 09:54:42 +02:00
parent 873ec84b52
commit d54a5c2ae0
5 changed files with 89 additions and 3 deletions

View File

@@ -425,6 +425,14 @@ class User < ApplicationRecord
end end
end end
def self.maximum_attempts
(Tenant.current_secrets.dig(:security, :lockable, :maximum_attempts) || 20).to_i
end
def self.unlock_in
(Tenant.current_secrets.dig(:security, :lockable, :unlock_in) || 1).to_f.hours
end
private private
def clean_document_number def clean_document_number

View File

@@ -181,10 +181,10 @@ Devise.setup do |config|
# Number of authentication tries before locking an account if lock_strategy # Number of authentication tries before locking an account if lock_strategy
# is failed attempts. # is failed attempts.
config.maximum_attempts = 20 config.maximum_attempts = 20 # Overwritten in User model
# Time interval to unlock the account if :time is enabled as unlock_strategy. # Time interval to unlock the account if :time is enabled as unlock_strategy.
config.unlock_in = 1.hour config.unlock_in = 1.hour # Overwritten in User model
# Warn on the last attempt before the account is locked. # Warn on the last attempt before the account is locked.
config.last_attempt_warning = false config.last_attempt_warning = false

View File

@@ -23,6 +23,9 @@ development:
security: security:
last_sign_in: false last_sign_in: false
password_complexity: false password_complexity: false
# lockable:
# maximum_attempts: 20
# unlock_in: 1 # In hours
secret_key_base: 56792feef405a59b18ea7db57b4777e855103882b926413d4afdfb8c0ea8aa86ea6649da4e729c5f5ae324c0ab9338f789174cf48c544173bc18fdc3b14262e4 secret_key_base: 56792feef405a59b18ea7db57b4777e855103882b926413d4afdfb8c0ea8aa86ea6649da4e729c5f5ae324c0ab9338f789174cf48c544173bc18fdc3b14262e4
<<: *maps <<: *maps
@@ -58,6 +61,9 @@ staging:
security: security:
last_sign_in: false last_sign_in: false
password_complexity: false password_complexity: false
# lockable:
# maximum_attempts: 20
# unlock_in: 1 # In hours
tenants: tenants:
# If you've enabled multitenancy, you can overwrite secrets for a # If you've enabled multitenancy, you can overwrite secrets for a
# specific tenant with: # specific tenant with:
@@ -98,6 +104,9 @@ preproduction:
security: security:
last_sign_in: false last_sign_in: false
password_complexity: false password_complexity: false
# lockable:
# maximum_attempts: 20
# unlock_in: 1 # In hours
tenants: tenants:
# If you've enabled multitenancy, you can overwrite secrets for a # If you've enabled multitenancy, you can overwrite secrets for a
# specific tenant with: # specific tenant with:
@@ -143,6 +152,9 @@ production:
security: security:
last_sign_in: false last_sign_in: false
password_complexity: false password_complexity: false
# lockable:
# maximum_attempts: 20
# unlock_in: 1 # In hours
tenants: tenants:
# If you've enabled multitenancy, you can overwrite secrets for a # If you've enabled multitenancy, you can overwrite secrets for a
# specific tenant with: # specific tenant with:

View File

@@ -8,7 +8,7 @@ describe Users::SessionsController do
describe "Devise lock" do describe "Devise lock" do
context "when devise sign in maximum_attempts reached", :with_frozen_time 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 it "locks the user account and sends an email to the account with an unlock link" do
user.update(failed_attempts: 19) allow(User).to receive(:maximum_attempts).and_return(1)
expect do expect do
post :create, params: { user: { login: "citizen@consul.org", password: "wrongpassword" }} post :create, params: { user: { login: "citizen@consul.org", password: "wrongpassword" }}

View File

@@ -882,4 +882,70 @@ describe User do
end end
end end
end end
describe ".maximum_attempts" do
it "returns 20 as default when the secrets aren't configured" do
expect(User.maximum_attempts).to eq 20
end
context "when secrets are configured" do
before do
allow(Rails.application).to receive(:secrets).and_return(ActiveSupport::OrderedOptions.new.merge(
security: {
lockable: { maximum_attempts: "14" }
},
tenants: {
superstrict: {
security: {
lockable: { maximum_attempts: "1" }
}
}
}
))
end
it "uses the general secrets for the main tenant" do
expect(User.maximum_attempts).to eq 14
end
it "uses the tenant secrets for a tenant" do
allow(Tenant).to receive(:current_schema).and_return("superstrict")
expect(User.maximum_attempts).to eq 1
end
end
end
describe ".unlock_in" do
it "returns 1 as default when the secrets aren't configured" do
expect(User.unlock_in).to eq 1.hour
end
context "when secrets are configured" do
before do
allow(Rails.application).to receive(:secrets).and_return(ActiveSupport::OrderedOptions.new.merge(
security: {
lockable: { unlock_in: "2" }
},
tenants: {
superstrict: {
security: {
lockable: { unlock_in: "50" }
}
}
}
))
end
it "uses the general secrets for the main tenant" do
expect(User.unlock_in).to eq 2.hours
end
it "uses the tenant secrets for a tenant" do
allow(Tenant).to receive(:current_schema).and_return("superstrict")
expect(User.unlock_in).to eq 50.hours
end
end
end
end end