Lines 41-46
use Koha::DateUtils;
Link Here
|
41 |
use Koha::Borrower::Debarments qw(IsDebarred); |
41 |
use Koha::Borrower::Debarments qw(IsDebarred); |
42 |
use Text::Unaccent qw( unac_string ); |
42 |
use Text::Unaccent qw( unac_string ); |
43 |
use Koha::AuthUtils qw(hash_password); |
43 |
use Koha::AuthUtils qw(hash_password); |
|
|
44 |
use App::Genpass; |
44 |
|
45 |
|
45 |
our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug); |
46 |
our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug); |
46 |
|
47 |
|
Lines 105-110
BEGIN {
Link Here
|
105 |
GetBorrowersWithEmail |
106 |
GetBorrowersWithEmail |
106 |
|
107 |
|
107 |
HasOverdues |
108 |
HasOverdues |
|
|
109 |
|
110 |
&GenMemberPasswordSuggestion |
111 |
&ValidateMemberPassword |
108 |
); |
112 |
); |
109 |
|
113 |
|
110 |
#Modify data |
114 |
#Modify data |
Lines 329-334
sub GetMemberDetails {
Link Here
|
329 |
SELECT borrowers.*, |
333 |
SELECT borrowers.*, |
330 |
category_type, |
334 |
category_type, |
331 |
categories.description, |
335 |
categories.description, |
|
|
336 |
categories.passwordpolicy, |
332 |
categories.BlockExpiredPatronOpacActions, |
337 |
categories.BlockExpiredPatronOpacActions, |
333 |
reservefee, |
338 |
reservefee, |
334 |
enrolmentperiod |
339 |
enrolmentperiod |
Lines 343-348
sub GetMemberDetails {
Link Here
|
343 |
SELECT borrowers.*, |
348 |
SELECT borrowers.*, |
344 |
category_type, |
349 |
category_type, |
345 |
categories.description, |
350 |
categories.description, |
|
|
351 |
categories.passwordpolicy, |
346 |
categories.BlockExpiredPatronOpacActions, |
352 |
categories.BlockExpiredPatronOpacActions, |
347 |
reservefee, |
353 |
reservefee, |
348 |
enrolmentperiod |
354 |
enrolmentperiod |
Lines 2613-2618
sub HasOverdues {
Link Here
|
2613 |
return $count; |
2619 |
return $count; |
2614 |
} |
2620 |
} |
2615 |
|
2621 |
|
|
|
2622 |
=head2 GenMemberPasswordSuggestion |
2623 |
|
2624 |
$password = GenMemberPasswordSuggestion($borrowernumber); |
2625 |
|
2626 |
Returns a new patron password suggestion based on borrowers password policy from categories |
2627 |
|
2628 |
=cut |
2629 |
|
2630 |
sub GenMemberPasswordSuggestion { |
2631 |
my $borrowernumber = shift; |
2632 |
my $minpasslength = C4::Context->preference('minPasswordLength'); |
2633 |
|
2634 |
my $borrowerinfo = GetMemberDetails($borrowernumber); |
2635 |
my $policycode = $borrowerinfo->{'passwordpolicy'}; |
2636 |
|
2637 |
my $pass; |
2638 |
my $length = int(rand(3)) + $minpasslength; |
2639 |
if ($policycode) { |
2640 |
# Generates complex passwords with numbers and uppercase, lowercase and special characters |
2641 |
if ($policycode eq "complex") { |
2642 |
my $specials = ['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_']; |
2643 |
$pass = App::Genpass->new(specials => $specials, readable => 0, length => $length); |
2644 |
} |
2645 |
|
2646 |
# Generates simple passwords with numbers and uppercase and lowercase characters |
2647 |
elsif ($policycode eq "alphanumeric") { |
2648 |
$pass = App::Genpass->new(length => $length); |
2649 |
} |
2650 |
|
2651 |
# Generates passwords with digits 0-9 only |
2652 |
else { |
2653 |
# verify => 0 due to a bug in generate() (workaround) |
2654 |
$pass = App::Genpass->new(lowercase => [], uppercase => [], verify => 0, length => $length); |
2655 |
} |
2656 |
} |
2657 |
# Defaults to empty constuctor which gives readable complex passwords |
2658 |
else { |
2659 |
$pass = App::Genpass->new(length => $length); |
2660 |
} |
2661 |
|
2662 |
return $pass->generate(); |
2663 |
} |
2664 |
|
2665 |
=head2 ValidateMemberPassword |
2666 |
|
2667 |
($success, $errorcode, $errormessage) = ValidateMemberPassword($borrowernumber, $newpassword1, $newpassword2); |
2668 |
|
2669 |
Validates a member's password based on category password policy and/or minPasswordLength |
2670 |
|
2671 |
=cut |
2672 |
|
2673 |
sub ValidateMemberPassword { |
2674 |
my ($borrowernumber, $newpassword1, $newpassword2) = @_; |
2675 |
my $minpasslength = C4::Context->preference('minPasswordLength'); |
2676 |
|
2677 |
if (!$borrowernumber) { |
2678 |
return (0, ,"NOBORROWER", "No borrowernumber given"); |
2679 |
} |
2680 |
|
2681 |
if ((!$newpassword1 || !$newpassword2) || ($newpassword1 ne $newpassword2)) { |
2682 |
return (0, "NOMATCH", "The passwords do not match"); |
2683 |
} |
2684 |
|
2685 |
if (length($newpassword1) < $minpasslength) { |
2686 |
return (0, "SHORTPASSWORD", "The password is too short"); |
2687 |
} |
2688 |
|
2689 |
my $memberinfo = GetMemberDetails($borrowernumber); |
2690 |
my $passwordpolicy = $memberinfo->{'passwordpolicy'}; |
2691 |
|
2692 |
if ($passwordpolicy) { |
2693 |
if ($passwordpolicy eq "simplenumeric") { |
2694 |
if ($newpassword1 !~ /[0-9]+/) { |
2695 |
return (0, "NOPOLICYMATCH", "Password policy: password can only contain digits 0-9"); |
2696 |
} |
2697 |
} |
2698 |
elsif ($passwordpolicy eq "alphanumeric") { |
2699 |
unless ($newpassword1 =~ /[0-9]/ |
2700 |
&& $newpassword1 =~ /[a-zA-ZöäåÖÄÅ]/ |
2701 |
&& $newpassword1 !~ /\W/ |
2702 |
&& $newpassword1 !~ /[_-]/) { |
2703 |
return (0, "NOPOLICYMATCH", "Password policy: password must contain both numbers and non-special characters (at least one of both)"); |
2704 |
} |
2705 |
} |
2706 |
else { |
2707 |
unless ($newpassword1 =~ /[0-9]/ |
2708 |
&& $newpassword1 =~ /[a-zåäö]/ |
2709 |
&& $newpassword1 =~ /[A-ZÅÄÖ]/ |
2710 |
&& $newpassword1 =~ /[\|\[\]\{\}!@#\$%\^&\*\(\)_\-\+\?]/) { |
2711 |
return (0, "NOPOLICYMATCH", "Password policy: password must contain numbers, characters and special characters (at least one of each)"); |
2712 |
} |
2713 |
} |
2714 |
} |
2715 |
return 1; |
2716 |
} |
2717 |
|
2616 |
END { } # module clean-up code here (global destructor) |
2718 |
END { } # module clean-up code here (global destructor) |
2617 |
|
2719 |
|
2618 |
1; |
2720 |
1; |