|
Lines 19-25
Link Here
|
| 19 |
|
19 |
|
| 20 |
use Modern::Perl; |
20 |
use Modern::Perl; |
| 21 |
|
21 |
|
| 22 |
use Test::More tests => 34; |
22 |
use Test::More tests => 39; |
| 23 |
use Test::Warn; |
23 |
use Test::Warn; |
| 24 |
use Test::Exception; |
24 |
use Test::Exception; |
| 25 |
use Test::MockModule; |
25 |
use Test::MockModule; |
|
Lines 1625-1627
subtest '->set_password' => sub {
Link Here
|
| 1625 |
|
1625 |
|
| 1626 |
$schema->storage->txn_rollback; |
1626 |
$schema->storage->txn_rollback; |
| 1627 |
}; |
1627 |
}; |
| 1628 |
- |
1628 |
|
|
|
1629 |
$schema->storage->txn_begin; |
| 1630 |
subtest 'search_unsubscribed' => sub { |
| 1631 |
plan tests => 4; |
| 1632 |
|
| 1633 |
t::lib::Mocks::mock_preference( 'FailedLoginAttempts', 3 ); |
| 1634 |
t::lib::Mocks::mock_preference( 'UnsubscribeReflectionDelay', '' ); |
| 1635 |
is( Koha::Patrons->search_unsubscribed->count, 0, 'Empty delay should return empty set' ); |
| 1636 |
|
| 1637 |
my $patron1 = $builder->build_object({ class => 'Koha::Patrons' }); |
| 1638 |
my $patron2 = $builder->build_object({ class => 'Koha::Patrons' }); |
| 1639 |
|
| 1640 |
t::lib::Mocks::mock_preference( 'UnsubscribeReflectionDelay', 0 ); |
| 1641 |
Koha::Patron::Consents->delete; # for correct counts |
| 1642 |
Koha::Patron::Consent->new({ borrowernumber => $patron1->borrowernumber, type => 'GDPR_PROCESSING', refused_on => dt_from_string })->store; |
| 1643 |
is( Koha::Patrons->search_unsubscribed->count, 1, 'Find patron1' ); |
| 1644 |
|
| 1645 |
# Add another refusal but shift the period |
| 1646 |
t::lib::Mocks::mock_preference( 'UnsubscribeReflectionDelay', 2 ); |
| 1647 |
Koha::Patron::Consent->new({ borrowernumber => $patron2->borrowernumber, type => 'GDPR_PROCESSING', refused_on => dt_from_string->subtract(days=>2) })->store; |
| 1648 |
is( Koha::Patrons->search_unsubscribed->count, 1, 'Find patron2 only' ); |
| 1649 |
|
| 1650 |
# Try another (special) attempts setting |
| 1651 |
t::lib::Mocks::mock_preference( 'FailedLoginAttempts', 0 ); |
| 1652 |
# Lockout is now disabled |
| 1653 |
# Patron2 still matches: refused earlier, not locked |
| 1654 |
is( Koha::Patrons->search_unsubscribed->count, 1, 'Lockout disabled' ); |
| 1655 |
}; |
| 1656 |
|
| 1657 |
subtest 'search_anonymize_candidates' => sub { |
| 1658 |
plan tests => 5; |
| 1659 |
my $patron1 = $builder->build_object({ class => 'Koha::Patrons' }); |
| 1660 |
my $patron2 = $builder->build_object({ class => 'Koha::Patrons' }); |
| 1661 |
$patron1->flgAnonymized(0); |
| 1662 |
$patron1->dateexpiry( dt_from_string->add(days => 1) )->store; |
| 1663 |
$patron2->flgAnonymized(undef); |
| 1664 |
$patron2->dateexpiry( dt_from_string->add(days => 1) )->store; |
| 1665 |
|
| 1666 |
t::lib::Mocks::mock_preference( 'PatronAnonymizeDelay', q{} ); |
| 1667 |
is( Koha::Patrons->search_anonymize_candidates->count, 0, 'Empty set' ); |
| 1668 |
|
| 1669 |
t::lib::Mocks::mock_preference( 'PatronAnonymizeDelay', 0 ); |
| 1670 |
my $cnt = Koha::Patrons->search_anonymize_candidates->count; |
| 1671 |
$patron1->dateexpiry( dt_from_string->subtract(days => 1) )->store; |
| 1672 |
$patron2->dateexpiry( dt_from_string->subtract(days => 3) )->store; |
| 1673 |
is( Koha::Patrons->search_anonymize_candidates->count, $cnt+2, 'Delay 0' ); |
| 1674 |
|
| 1675 |
t::lib::Mocks::mock_preference( 'PatronAnonymizeDelay', 2 ); |
| 1676 |
$patron1->dateexpiry( dt_from_string->add(days => 1) )->store; |
| 1677 |
$patron2->dateexpiry( dt_from_string->add(days => 1) )->store; |
| 1678 |
$cnt = Koha::Patrons->search_anonymize_candidates->count; |
| 1679 |
$patron1->dateexpiry( dt_from_string->subtract(days => 1) )->store; |
| 1680 |
$patron2->dateexpiry( dt_from_string->subtract(days => 3) )->store; |
| 1681 |
is( Koha::Patrons->search_anonymize_candidates->count, $cnt+1, 'Delay 2' ); |
| 1682 |
|
| 1683 |
t::lib::Mocks::mock_preference( 'PatronAnonymizeDelay', 4 ); |
| 1684 |
$patron1->dateexpiry( dt_from_string->add(days => 1) )->store; |
| 1685 |
$patron2->dateexpiry( dt_from_string->add(days => 1) )->store; |
| 1686 |
$cnt = Koha::Patrons->search_anonymize_candidates->count; |
| 1687 |
$patron1->dateexpiry( dt_from_string->subtract(days => 1) )->store; |
| 1688 |
$patron2->dateexpiry( dt_from_string->subtract(days => 3) )->store; |
| 1689 |
is( Koha::Patrons->search_anonymize_candidates->count, $cnt, 'Delay 4' ); |
| 1690 |
|
| 1691 |
t::lib::Mocks::mock_preference( 'FailedLoginAttempts', 3 ); |
| 1692 |
$patron1->dateexpiry( dt_from_string->subtract(days => 5) )->store; |
| 1693 |
$patron1->login_attempts(0)->store; |
| 1694 |
$patron2->dateexpiry( dt_from_string->subtract(days => 5) )->store; |
| 1695 |
$patron2->login_attempts(0)->store; |
| 1696 |
$cnt = Koha::Patrons->search_anonymize_candidates({locked => 1})->count; |
| 1697 |
$patron1->login_attempts(3)->store; |
| 1698 |
is( Koha::Patrons->search_anonymize_candidates({locked => 1})->count, |
| 1699 |
$cnt+1, 'Locked flag' ); |
| 1700 |
}; |
| 1701 |
|
| 1702 |
subtest 'search_anonymized' => sub { |
| 1703 |
plan tests => 3; |
| 1704 |
my $patron1 = $builder->build_object( { class => 'Koha::Patrons' } ); |
| 1705 |
|
| 1706 |
t::lib::Mocks::mock_preference( 'PatronRemovalDelay', q{} ); |
| 1707 |
is( Koha::Patrons->search_anonymized->count, 0, 'Empty set' ); |
| 1708 |
|
| 1709 |
t::lib::Mocks::mock_preference( 'PatronRemovalDelay', 1 ); |
| 1710 |
$patron1->dateexpiry( dt_from_string ); |
| 1711 |
$patron1->flgAnonymized(0)->store; |
| 1712 |
my $cnt = Koha::Patrons->search_anonymized->count; |
| 1713 |
$patron1->flgAnonymized(1)->store; |
| 1714 |
is( Koha::Patrons->search_anonymized->count, $cnt, 'Number unchanged' ); |
| 1715 |
$patron1->dateexpiry( dt_from_string->subtract(days => 1) )->store; |
| 1716 |
is( Koha::Patrons->search_anonymized->count, $cnt+1, 'Found patron1' ); |
| 1717 |
}; |
| 1718 |
|
| 1719 |
subtest 'lock' => sub { |
| 1720 |
plan tests => 8; |
| 1721 |
|
| 1722 |
my $patron1 = $builder->build_object( { class => 'Koha::Patrons' } ); |
| 1723 |
my $patron2 = $builder->build_object( { class => 'Koha::Patrons' } ); |
| 1724 |
my $hold = $builder->build_object({ |
| 1725 |
class => 'Koha::Holds', |
| 1726 |
value => { borrowernumber => $patron1->borrowernumber }, |
| 1727 |
}); |
| 1728 |
|
| 1729 |
t::lib::Mocks::mock_preference( 'FailedLoginAttempts', 3 ); |
| 1730 |
my $expiry = dt_from_string->add(days => 1); |
| 1731 |
$patron1->dateexpiry( $expiry ); |
| 1732 |
$patron1->lock; |
| 1733 |
is( $patron1->login_attempts, Koha::Patron::ADMINISTRATIVE_LOCKOUT, 'Check login_attempts' ); |
| 1734 |
is( $patron1->dateexpiry, $expiry, 'Not expired yet' ); |
| 1735 |
is( $patron1->holds->count, 1, 'No holds removed' ); |
| 1736 |
|
| 1737 |
$patron1->lock({ expire => 1, remove => 1}); |
| 1738 |
isnt( $patron1->dateexpiry, $expiry, 'Expiry date adjusted' ); |
| 1739 |
is( $patron1->holds->count, 0, 'Holds removed' ); |
| 1740 |
|
| 1741 |
# Disable lockout feature |
| 1742 |
t::lib::Mocks::mock_preference( 'FailedLoginAttempts', q{} ); |
| 1743 |
$patron1->login_attempts(0); |
| 1744 |
$patron1->dateexpiry( $expiry ); |
| 1745 |
$patron1->store; |
| 1746 |
$patron1->lock; |
| 1747 |
is( $patron1->login_attempts, Koha::Patron::ADMINISTRATIVE_LOCKOUT, 'Check login_attempts' ); |
| 1748 |
|
| 1749 |
# Trivial wrapper test (Koha::Patrons->lock) |
| 1750 |
$patron1->login_attempts(0)->store; |
| 1751 |
Koha::Patrons->search({ borrowernumber => [ $patron1->borrowernumber, $patron2->borrowernumber ] })->lock; |
| 1752 |
$patron1->discard_changes; # refresh |
| 1753 |
$patron2->discard_changes; |
| 1754 |
is( $patron1->login_attempts, Koha::Patron::ADMINISTRATIVE_LOCKOUT, 'Check login_attempts patron 1' ); |
| 1755 |
is( $patron2->login_attempts, Koha::Patron::ADMINISTRATIVE_LOCKOUT, 'Check login_attempts patron 2' ); |
| 1756 |
}; |
| 1757 |
|
| 1758 |
subtest 'anonymize' => sub { |
| 1759 |
plan tests => 9; |
| 1760 |
|
| 1761 |
my $patron1 = $builder->build_object( { class => 'Koha::Patrons' } ); |
| 1762 |
my $patron2 = $builder->build_object( { class => 'Koha::Patrons' } ); |
| 1763 |
|
| 1764 |
# First try patron with issues |
| 1765 |
my $issue = $builder->build_object({ class => 'Koha::Checkouts', value => { borrowernumber => $patron2->borrowernumber } }); |
| 1766 |
warning_like { $patron2->anonymize } qr/still has issues/, 'Skip patron with issues'; |
| 1767 |
$issue->delete; |
| 1768 |
|
| 1769 |
t::lib::Mocks::mock_preference( 'BorrowerMandatoryField', 'surname|email|cardnumber' ); |
| 1770 |
my $surname = $patron1->surname; # expect change, no clear |
| 1771 |
my $branchcode = $patron1->branchcode; # expect skip |
| 1772 |
$patron1->anonymize; |
| 1773 |
is($patron1->flgAnonymized, 1, 'Check flag' ); |
| 1774 |
|
| 1775 |
is( $patron1->dateofbirth, undef, 'Birth date cleared' ); |
| 1776 |
is( $patron1->firstname, undef, 'First name cleared' ); |
| 1777 |
isnt( $patron1->surname, $surname, 'Surname changed' ); |
| 1778 |
ok( $patron1->surname =~ /^\w{10}$/, 'Mandatory surname randomized' ); |
| 1779 |
is( $patron1->branchcode, $branchcode, 'Branch code skipped' ); |
| 1780 |
|
| 1781 |
# Test wrapper in Koha::Patrons |
| 1782 |
$patron1->surname($surname)->store; # restore |
| 1783 |
my $rs = Koha::Patrons->search({ borrowernumber => [ $patron1->borrowernumber, $patron2->borrowernumber ] })->anonymize; |
| 1784 |
$patron1->discard_changes; # refresh |
| 1785 |
isnt( $patron1->surname, $surname, 'Surname patron1 changed again' ); |
| 1786 |
$patron2->discard_changes; # refresh |
| 1787 |
is( $patron2->firstname, undef, 'First name patron2 cleared' ); |
| 1788 |
}; |
| 1789 |
$schema->storage->txn_rollback; |