From 4baf3b34fa584628613e9f97ef6597679c361aff Mon Sep 17 00:00:00 2001 From: Emmi Takkinen Date: Thu, 7 May 2020 13:58:30 +0300 Subject: [PATCH] Bug 12617: Add syspref PasswordLengthsForCategories Sometimes different patron categories using same password policy would require different lengths in their passwords. In these cases having one length per policy isn't always ideal. This patch adds new syspref 'PasswordLengthsForCategories' to define password lengths for different patron categories in YAML format and removes use of 'minAlnumPasswordLength' and 'minComplexPasswordLength'. If category has no rule set syspref 'minPasswordLength' is used. To test: 1. Run updatedatabase.pl 2. Define some rules to 'PasswordLengthsForCategories' (e.g example provided) 3. Try setting and changing password in different pages (basically follow test plans from previous patches). 4. Confirm error messages are displayed correctly. Also prove t/AuthUtils.t. Sponsored-by: Koha-Suomi Oy --- Koha/AuthUtils.pm | 33 +++++++++++++------ ...-syspref-PasswordLengthsForCategories.perl | 19 +++++++++++ installer/data/mysql/sysprefs.sql | 1 + .../en/modules/admin/preferences/patrons.pref | 12 +++++++ t/AuthUtils.t | 25 ++++++++++---- 5 files changed, 73 insertions(+), 17 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/Bug-12617-Add-syspref-PasswordLengthsForCategories.perl diff --git a/Koha/AuthUtils.pm b/Koha/AuthUtils.pm index 493193dfd6..f5c375dab9 100644 --- a/Koha/AuthUtils.pm +++ b/Koha/AuthUtils.pm @@ -23,6 +23,7 @@ use Encode qw( encode is_utf8 ); use Fcntl qw/O_RDONLY/; # O_RDONLY is used in generate_salt use List::MoreUtils qw/ any /; use String::Random qw( random_string random_regex ); +use YAML qw/Load/; use C4::Context; use Koha::Patron::Categories; @@ -235,17 +236,29 @@ Returns correct minPasswordLength sub min_password_length { my $categorycode = shift; - my $categoryinfo = Koha::Patron::Categories->find($categorycode); - my $passwordpolicy = $categoryinfo ? $categoryinfo->passwordpolicy : undef; - my $minpasslen; - if ($passwordpolicy eq "complex") { - $minpasslen = C4::Context->preference("minComplexPasswordLength"); - }elsif ($passwordpolicy eq "alphanumeric") { - $minpasslen = C4::Context->preference("minAlnumPasswordLength"); - }else { - $minpasslen = C4::Context->preference("minPasswordLength"); + my $password_lengths = C4::Context->preference('PasswordLengthsForCategories') || [] ; + if($password_lengths){ + $password_lengths = eval { YAML::Load( + Encode::encode( + 'UTF-8', + $password_lengths, + Encode::FB_CROAK + ))}; + + return (0, "YAMLERROR", "There's a problem in your 'PasswordLengthsForCategories': $@.") if $@; } - return $minpasslen; + + my $minPasswordLength; + + foreach my $password_length (@{$password_lengths}){ + if(grep( $_ eq $categorycode, @{$password_length->{'categories'}})){ + $minPasswordLength = $password_length->{'minlength'}; + } + } + + $minPasswordLength = C4::Context->preference("minPasswordLength") unless $minPasswordLength; + + return $minPasswordLength; } diff --git a/installer/data/mysql/atomicupdate/Bug-12617-Add-syspref-PasswordLengthsForCategories.perl b/installer/data/mysql/atomicupdate/Bug-12617-Add-syspref-PasswordLengthsForCategories.perl new file mode 100644 index 0000000000..3c66e49962 --- /dev/null +++ b/installer/data/mysql/atomicupdate/Bug-12617-Add-syspref-PasswordLengthsForCategories.perl @@ -0,0 +1,19 @@ +$DBversion = 'XXX'; # will be replaced by the RM +if( CheckVersion( $DBversion ) ) { + $dbh->do( + "INSERT IGNORE INTO systempreferences (variable, value, options, explanation, type) VALUES ('PasswordLengthsForCategories', '', NULL, 'Used to determine password lengths for different patron categories in a YAML format.', 'textarea')" + ); + $dbh->do( + "DELETE FROM systempreferences WHERE variable = 'minAlnumPasswordLengt'" + ); + $dbh->do( + "DELETE FROM systempreferences WHERE variable = 'minComplexPasswordLength'" + ); + $dbh->do( + "UPDATE systempreferences SET explanation = 'Specify the minimum length of a patron/staff password' where variable = 'minPasswordLength'" + ); + + # Always end with this (adjust the bug info) + SetVersion( $DBversion ); + print "Upgrade to $DBversion done (Bug 12617 - Add syspref PasswordLengthsForCategories)\n"; +} \ No newline at end of file diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index 2cbd12cc73..4b6f64669a 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -482,6 +482,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('OverdueNoticeCalendar',0,NULL,'Take the calendar into consideration when generating overdue notices','YesNo'), ('OverduesBlockCirc','noblock','noblock|confirmation|block','When checking out an item should overdues block checkout, generate a confirmation dialogue, or allow checkout','Choice'), ('OverduesBlockRenewing','allow','allow|blockitem|block','If any of patron checked out documents is late, should renewal be allowed, blocked only on overdue items or blocked on whatever checked out document','Choice'), +('PasswordLengthsForCategories', '', NULL, 'Used to determine password lengths for different patron categories in a YAML format.', 'textarea') ('PatronAnonymizeDelay','',NULL,'Delay for anonymizing patrons', 'Integer'), ('PatronAutoComplete','1','Try|Don\'t try','to guess the patron being entered while typing a patron search for circulation or patron search. Only returns the first 10 results at a time.','YesNo'), ('patronimages','0',NULL,'Enable patron images for the Staff Client','YesNo'), diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref index 471a8ebe84..5eb2c89c3f 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/patrons.pref @@ -367,3 +367,15 @@ Patrons: location: "Location" itemcallnumber: "Item's callnumber" ccode: "Collection code" + - + - pref: PasswordLengthsForCategories + type: textarea + class: code + - Define password lengths for different patron categories. + -
E.g + - "
-" + - "
 categories: [PT, K]" + - "
 minlength: 7" + - "
-" + - "
 categories: [S]" + - "
 minlength: 4" diff --git a/t/AuthUtils.t b/t/AuthUtils.t index 495a38ea75..22cdc79265 100644 --- a/t/AuthUtils.t +++ b/t/AuthUtils.t @@ -70,9 +70,6 @@ my $category_complex = $builder->build({ }, }); -t::lib::Mocks::mock_preference('minAlnumPasswordLength', 5); -t::lib::Mocks::mock_preference('minComplexPasswordLength', 6); - subtest 'is_password_valid' => sub { plan tests => 13; @@ -107,7 +104,21 @@ subtest 'is_password_valid' => sub { subtest 'password policies' => sub { t::lib::Mocks::mock_preference('RequireStrongPassword', 0); - t::lib::Mocks::mock_preference('minPasswordLength', 4); + t::lib::Mocks::mock_preference('minPasswordLength', 3); + + my $YAML =' + - + categories: ['.$category_simple->{categorycode}.'] + minlength: 4 + - + categories: ['.$category_alpha->{categorycode}.'] + minlength: 5 + - + categories: ['.$category_complex->{categorycode}.'] + minlength: 6 + '; + + t::lib::Mocks::mock_preference('PasswordLengthsForCategories', $YAML); #test simplenumeric password policy ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( '1234', $category_simple->{categorycode} ); @@ -118,7 +129,7 @@ subtest 'is_password_valid' => sub { ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( '!234', $category_simple->{categorycode} ); is ( $is_valid, 0, 'simplenumeric password should not contain non-special characters' ); ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( '123', $category_simple->{categorycode} ); - is ( $is_valid, 0, 'simplenumeric password follows minPasswordLength syspref' ); + is ( $is_valid, 0, 'simplenumeric password follows PasswordLengthsForCategories syspref' ); #test alphanumeric ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( 'A1234', $category_alpha->{categorycode} ); @@ -127,7 +138,7 @@ subtest 'is_password_valid' => sub { is ( $is_valid, 0, 'alphanumeric password must contain at least one uppercase character' ); is($error, 'alpha_policy_mismatch', 'error "alpha_policy_mismatch" raised'); ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( 'A123', $category_alpha->{categorycode} ); - is ( $is_valid, 0, 'alphanumeric password follows minAlnumPasswordLength syspref'); + is ( $is_valid, 0, 'alphanumeric password follows PasswordLengthsForCategories syspref'); #test complex ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( 'As!123', $category_complex->{categorycode} ); @@ -136,7 +147,7 @@ subtest 'is_password_valid' => sub { is ( $is_valid, 0, 'complex password must contain numbers, lower and uppercase characters and special characters' ); is($error, 'complex_policy_mismatch', 'error "complex_policy_mismatch" raised'); ( $is_valid, $error ) = Koha::AuthUtils::is_password_valid( 'As!12', $category_complex->{categorycode}); - is ( $is_valid, 0, 'complex password follows minComplexPasswordLength syspref' ); + is ( $is_valid, 0, 'complex password follows PasswordLengthsForCategories syspref' ); } }; -- 2.17.1