|
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; |