Validate password strength for internal users
This commit is contained in:
1
Gemfile
1
Gemfile
@ -49,6 +49,7 @@ gem 'telegraf'
|
|||||||
gem 'tubesock'
|
gem 'tubesock'
|
||||||
gem 'turbolinks'
|
gem 'turbolinks'
|
||||||
gem 'whenever', require: false
|
gem 'whenever', require: false
|
||||||
|
gem 'zxcvbn-ruby', require: 'zxcvbn'
|
||||||
|
|
||||||
# Error Tracing
|
# Error Tracing
|
||||||
gem 'mnemosyne-ruby'
|
gem 'mnemosyne-ruby'
|
||||||
|
@ -540,6 +540,7 @@ GEM
|
|||||||
xpath (3.2.0)
|
xpath (3.2.0)
|
||||||
nokogiri (~> 1.8)
|
nokogiri (~> 1.8)
|
||||||
zeitwerk (2.6.0)
|
zeitwerk (2.6.0)
|
||||||
|
zxcvbn-ruby (1.2.0)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
@ -623,6 +624,7 @@ DEPENDENCIES
|
|||||||
web-console
|
web-console
|
||||||
webmock
|
webmock
|
||||||
whenever
|
whenever
|
||||||
|
zxcvbn-ruby
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
2.3.17
|
2.3.17
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'zxcvbn'
|
||||||
|
|
||||||
class InternalUser < User
|
class InternalUser < User
|
||||||
authenticates_with_sorcery!
|
authenticates_with_sorcery!
|
||||||
|
|
||||||
@ -7,6 +9,7 @@ class InternalUser < User
|
|||||||
|
|
||||||
validates :email, presence: true, uniqueness: true
|
validates :email, presence: true, uniqueness: true
|
||||||
validates :password, confirmation: true, if: -> { password_void? && validate_password? }, on: :update, presence: true
|
validates :password, confirmation: true, if: -> { password_void? && validate_password? }, on: :update, presence: true
|
||||||
|
validate :password_strength, if: -> { password_void? && validate_password? }, on: :update
|
||||||
validates :role, inclusion: {in: ROLES}
|
validates :role, inclusion: {in: ROLES}
|
||||||
|
|
||||||
def activated?
|
def activated?
|
||||||
@ -25,6 +28,11 @@ class InternalUser < User
|
|||||||
end
|
end
|
||||||
private :validate_password?
|
private :validate_password?
|
||||||
|
|
||||||
|
def password_strength
|
||||||
|
result = Zxcvbn.test(password, [email, name, 'CodeOcean'])
|
||||||
|
errors.add(:password, :weak) if result.score < 4
|
||||||
|
end
|
||||||
|
|
||||||
def teacher?
|
def teacher?
|
||||||
role == 'teacher'
|
role == 'teacher'
|
||||||
end
|
end
|
||||||
|
@ -238,6 +238,10 @@ de:
|
|||||||
at_most_one_main_file: dürfen höchstens eine Hauptdatei enthalten
|
at_most_one_main_file: dürfen höchstens eine Hauptdatei enthalten
|
||||||
late_submission_deadline_not_alone: darf nicht ohne eine reguläre Abgabefrist verwendet werden
|
late_submission_deadline_not_alone: darf nicht ohne eine reguläre Abgabefrist verwendet werden
|
||||||
late_submission_deadline_not_before_submission_deadline: darf nicht vor der reguläre Abgabefrist liegen
|
late_submission_deadline_not_before_submission_deadline: darf nicht vor der reguläre Abgabefrist liegen
|
||||||
|
internal_user:
|
||||||
|
attributes:
|
||||||
|
password:
|
||||||
|
weak: ist zu schwach. Versuchen Sie es mit einem langen Passwort, welches Groß-, Kleinbuchstaben, Zahlen und Sonderzeichen enthält.
|
||||||
admin:
|
admin:
|
||||||
dashboard:
|
dashboard:
|
||||||
show:
|
show:
|
||||||
|
@ -238,6 +238,10 @@ en:
|
|||||||
at_most_one_main_file: must include at most one main file
|
at_most_one_main_file: must include at most one main file
|
||||||
late_submission_deadline_not_alone: must not be used without a regular submission deadline
|
late_submission_deadline_not_alone: must not be used without a regular submission deadline
|
||||||
late_submission_deadline_not_before_submission_deadline: must not be before the submission deadline passed
|
late_submission_deadline_not_before_submission_deadline: must not be before the submission deadline passed
|
||||||
|
internal_user:
|
||||||
|
attributes:
|
||||||
|
password:
|
||||||
|
weak: is too weak. Try to use a long password with upper and lower case letters, numbers and special characters.
|
||||||
admin:
|
admin:
|
||||||
dashboard:
|
dashboard:
|
||||||
show:
|
show:
|
||||||
|
@ -282,12 +282,29 @@ describe InternalUsersController do
|
|||||||
|
|
||||||
expect_assigns(user: :user)
|
expect_assigns(user: :user)
|
||||||
|
|
||||||
|
context 'with a weak password' do
|
||||||
|
let(:password) { 'foo' }
|
||||||
|
|
||||||
|
it 'does not change the password' do
|
||||||
|
expect { perform_request.call }.not_to change { user.reload.crypted_password }
|
||||||
|
expect(InternalUser.authenticate(user.email, password)).not_to eq(user)
|
||||||
|
end
|
||||||
|
|
||||||
|
expect_http_status(:ok)
|
||||||
|
expect_template(:reset_password)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a strong password' do
|
||||||
|
let(:password) { SecureRandom.hex(128) }
|
||||||
|
|
||||||
it 'changes the password' do
|
it 'changes the password' do
|
||||||
|
expect { perform_request.call }.not_to change { user.reload.crypted_password }
|
||||||
expect(InternalUser.authenticate(user.email, password)).to eq(user)
|
expect(InternalUser.authenticate(user.email, password)).to eq(user)
|
||||||
end
|
end
|
||||||
|
|
||||||
expect_redirect(:sign_in)
|
expect_redirect(:sign_in)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'without a matching password confirmation' do
|
context 'without a matching password confirmation' do
|
||||||
before do
|
before do
|
||||||
|
Reference in New Issue
Block a user