View | Details | Raw Unified | Return to bug 29924
Collapse All | Expand All

(-)a/C4/Auth.pm (-3 / +9 lines)
Lines 932-937 sub checkauth { Link Here
932
                $info{oldip}        = $more_info->{old_ip};
932
                $info{oldip}        = $more_info->{old_ip};
933
                $info{newip}        = $more_info->{new_ip};
933
                $info{newip}        = $more_info->{new_ip};
934
                $info{different_ip} = 1;
934
                $info{different_ip} = 1;
935
            } elsif ( $return eq 'password_expired' ) {
936
                $info{password_has_expired} = 1;
935
            }
937
            }
936
        }
938
        }
937
    }
939
    }
Lines 1316-1322 sub checkauth { Link Here
1316
        PatronSelfRegistration                => C4::Context->preference("PatronSelfRegistration"),
1318
        PatronSelfRegistration                => C4::Context->preference("PatronSelfRegistration"),
1317
        PatronSelfRegistrationDefaultCategory => C4::Context->preference("PatronSelfRegistrationDefaultCategory"),
1319
        PatronSelfRegistrationDefaultCategory => C4::Context->preference("PatronSelfRegistrationDefaultCategory"),
1318
        opac_css_override                     => $ENV{'OPAC_CSS_OVERRIDE'},
1320
        opac_css_override                     => $ENV{'OPAC_CSS_OVERRIDE'},
1319
        too_many_login_attempts               => ( $patron and $patron->account_locked )
1321
        too_many_login_attempts               => ( $patron and $patron->account_locked ),
1322
        password_has_expired                  => ( $patron and $patron->password_expired )
1320
    );
1323
    );
1321
1324
1322
    $template->param( SCO_login => 1 ) if ( $query->param('sco_user_login') );
1325
    $template->param( SCO_login => 1 ) if ( $query->param('sco_user_login') );
Lines 1693-1698 sub check_cookie_auth { Link Here
1693
1696
1694
        } elsif ( $userid ) {
1697
        } elsif ( $userid ) {
1695
            $session->param( 'lasttime', time() );
1698
            $session->param( 'lasttime', time() );
1699
            my $patron = Koha::Patrons->find({ userid => $userid });
1700
            $patron = Koha::Patron->find({ cardnumber => $userid }) unless $patron;
1701
            return ("password_expired", undef ) if $patron->password_expired;
1696
            my $flags = defined($flagsrequired) ? haspermission( $userid, $flagsrequired ) : 1;
1702
            my $flags = defined($flagsrequired) ? haspermission( $userid, $flagsrequired ) : 1;
1697
            if ($flags) {
1703
            if ($flags) {
1698
                C4::Context->_new_userenv($sessionID);
1704
                C4::Context->_new_userenv($sessionID);
Lines 1801-1808 sub checkpw { Link Here
1801
    # 0 if auth is nok
1807
    # 0 if auth is nok
1802
    # -1 if user bind failed (LDAP only)
1808
    # -1 if user bind failed (LDAP only)
1803
1809
1804
    if ( $patron and $patron->account_locked ) {
1810
    if ( $patron and ( $patron->account_locked || $patron->password_expired )  ) {
1805
        # Nothing to check, account is locked
1811
        # Nothing to check, account is locked or password expired
1806
    } elsif ($ldap && defined($password)) {
1812
    } elsif ($ldap && defined($password)) {
1807
        my ( $retval, $retcard, $retuserid ) = checkpw_ldap(@_);    # EXTERNAL AUTH
1813
        my ( $retval, $retcard, $retuserid ) = checkpw_ldap(@_);    # EXTERNAL AUTH
1808
        if ( $retval == 1 ) {
1814
        if ( $retval == 1 ) {
(-)a/Koha/Patron.pm (+20 lines)
Lines 264-269 sub store { Link Here
264
                # Make a copy of the plain text password for later use
264
                # Make a copy of the plain text password for later use
265
                $self->plain_text_password( $self->password );
265
                $self->plain_text_password( $self->password );
266
266
267
                $self->password_expiration_date( $self->password
268
                    ? $self->category->get_password_expiry_date
269
                    : undef );
267
                # Create a disabled account if no password provided
270
                # Create a disabled account if no password provided
268
                $self->password( $self->password
271
                $self->password( $self->password
269
                    ? Koha::AuthUtils::hash_password( $self->password )
272
                    ? Koha::AuthUtils::hash_password( $self->password )
Lines 777-782 sub is_expired { Link Here
777
    return 0;
780
    return 0;
778
}
781
}
779
782
783
=head3 password_expired
784
785
my $password_expired = $patron->password_expired;
786
787
Returns 1 if the patron's password is expired or 0;
788
789
=cut
790
791
sub password_expired {
792
    my ($self) = @_;
793
    return 0 unless $self->password_expiration_date;
794
    return 1 if dt_from_string( $self->password_expiration_date ) < dt_from_string->truncate( to => 'day' );
795
    return 0;
796
}
797
780
=head3 is_going_to_expire
798
=head3 is_going_to_expire
781
799
782
my $is_going_to_expire = $patron->is_going_to_expire;
800
my $is_going_to_expire = $patron->is_going_to_expire;
Lines 876-881 sub set_password { Link Here
876
894
877
    my $digest = Koha::AuthUtils::hash_password($password);
895
    my $digest = Koha::AuthUtils::hash_password($password);
878
896
897
    $self->password_expiration_date( $self->category->get_password_expiry_date );
898
879
    # We do not want to call $self->store and retrieve password from DB
899
    # We do not want to call $self->store and retrieve password from DB
880
    $self->password($digest);
900
    $self->password($digest);
881
    $self->login_attempts(0);
901
    $self->login_attempts(0);
(-)a/Koha/Patron/Category.pm (+20 lines)
Lines 113-118 sub get_expiry_date { Link Here
113
    }
113
    }
114
}
114
}
115
115
116
=head3 get_password_expiry_date
117
118
Returns date based on password expiry days set for the category. If the value is not set
119
we return undef, password does not expire
120
121
my $expiry_date = $category->get_password_expiry_date();
122
123
=cut
124
125
sub get_password_expiry_date {
126
    my ($self, $date ) = @_;
127
    if ( $self->password_expiry_days ) {
128
        $date ||= dt_from_string;
129
        $date = dt_from_string( $date ) unless ref $date;
130
        return $date->add( days => $self->password_expiry_days )->ymd;
131
    } else {
132
        return;
133
    }
134
}
135
116
=head3 effective_reset_password
136
=head3 effective_reset_password
117
137
118
Returns if patrons in this category can reset their password. If set in $self->reset_password
138
Returns if patrons in this category can reset their password. If set in $self->reset_password
(-)a/Koha/REST/V1/Auth.pm (-1 / +6 lines)
Lines 491-497 sub _basic_auth { Link Here
491
        Koha::Exceptions::Authorization::Unauthorized->throw( error => 'Invalid password' );
491
        Koha::Exceptions::Authorization::Unauthorized->throw( error => 'Invalid password' );
492
    }
492
    }
493
493
494
    return Koha::Patrons->find({ userid => $user_id });
494
    my $patron = Koha::Patrons->find({ userid => $user_id });
495
    if ( $patron->password_expired ) {
496
        Koha::Exceptions::Authorization::Unauthorized->throw( error => 'Password has expired' );
497
    }
498
499
    return $patron;
495
}
500
}
496
501
497
=head3 _set_userenv
502
=head3 _set_userenv
(-)a/admin/categories.pl (+3 lines)
Lines 63-68 elsif ( $op eq 'add_validate' ) { Link Here
63
    my $description = $input->param('description');
63
    my $description = $input->param('description');
64
    my $enrolmentperiod = $input->param('enrolmentperiod');
64
    my $enrolmentperiod = $input->param('enrolmentperiod');
65
    my $enrolmentperioddate = $input->param('enrolmentperioddate') || undef;
65
    my $enrolmentperioddate = $input->param('enrolmentperioddate') || undef;
66
    my $password_expiry_days = $input->param('password_expiry_days') || undef;
66
    my $upperagelimit = $input->param('upperagelimit');
67
    my $upperagelimit = $input->param('upperagelimit');
67
    my $dateofbirthrequired = $input->param('dateofbirthrequired');
68
    my $dateofbirthrequired = $input->param('dateofbirthrequired');
68
    my $enrolmentfee = $input->param('enrolmentfee');
69
    my $enrolmentfee = $input->param('enrolmentfee');
Lines 103-108 elsif ( $op eq 'add_validate' ) { Link Here
103
        $category->description($description);
104
        $category->description($description);
104
        $category->enrolmentperiod($enrolmentperiod);
105
        $category->enrolmentperiod($enrolmentperiod);
105
        $category->enrolmentperioddate($enrolmentperioddate);
106
        $category->enrolmentperioddate($enrolmentperioddate);
107
        $category->password_expiry_days($password_expiry_days);
106
        $category->upperagelimit($upperagelimit);
108
        $category->upperagelimit($upperagelimit);
107
        $category->dateofbirthrequired($dateofbirthrequired);
109
        $category->dateofbirthrequired($dateofbirthrequired);
108
        $category->enrolmentfee($enrolmentfee);
110
        $category->enrolmentfee($enrolmentfee);
Lines 134-139 elsif ( $op eq 'add_validate' ) { Link Here
134
            description => $description,
136
            description => $description,
135
            enrolmentperiod => $enrolmentperiod,
137
            enrolmentperiod => $enrolmentperiod,
136
            enrolmentperioddate => $enrolmentperioddate,
138
            enrolmentperioddate => $enrolmentperioddate,
139
            password_expiry_days => $password_expiry_days,
137
            upperagelimit => $upperagelimit,
140
            upperagelimit => $upperagelimit,
138
            dateofbirthrequired => $dateofbirthrequired,
141
            dateofbirthrequired => $dateofbirthrequired,
139
            enrolmentfee => $enrolmentfee,
142
            enrolmentfee => $enrolmentfee,
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/categories.tt (+11 lines)
Lines 162-167 Link Here
162
                        </ol>
162
                        </ol>
163
                    </fieldset>
163
                    </fieldset>
164
                </li>
164
                </li>
165
                <li>
166
                    <label for="password_expiry_days">Password expiration: </label>
167
                    <input type="text" name="password_expiry_days" id="password_expiry_days" value="[% category.password_expiry_days | html %]" size="3" maxlength="5" /> days
168
                </li>
165
                <li>
169
                <li>
166
                    <label for="dateofbirthrequired">Age required: </label>
170
                    <label for="dateofbirthrequired">Age required: </label>
167
                    <input type="text" name="dateofbirthrequired" id="dateofbirthrequired" value="[% category.dateofbirthrequired | html %]" size="3" maxlength="3" /> years
171
                    <input type="text" name="dateofbirthrequired" id="dateofbirthrequired" value="[% category.dateofbirthrequired | html %]" size="3" maxlength="3" /> years
Lines 449-454 Link Here
449
                        [% END %]
453
                        [% END %]
450
                    </td>
454
                    </td>
451
                </tr>
455
                </tr>
456
                <tr><th scope="row">Password expiration: </th><td>[% category.password_expiry_days | html %] days</td></tr>
452
                <tr><th scope="row">Age required: </th><td>[% category.dateofbirthrequired | html %] years</td></tr>
457
                <tr><th scope="row">Age required: </th><td>[% category.dateofbirthrequired | html %] years</td></tr>
453
                <tr><th scope="row">Upperage limit: </th><td>[% category.upperagelimit | html %] years</td></tr>
458
                <tr><th scope="row">Upperage limit: </th><td>[% category.upperagelimit | html %] years</td></tr>
454
                <tr><th scope="row">Enrollment fee: </th><td>[% category.enrolmentfee | $Price %]</td></tr>
459
                <tr><th scope="row">Enrollment fee: </th><td>[% category.enrolmentfee | $Price %]</td></tr>
Lines 517-522 Link Here
517
                    <th scope="col">Category name</th>
522
                    <th scope="col">Category name</th>
518
                    <th scope="col">Type</th>
523
                    <th scope="col">Type</th>
519
                    <th scope="col">Enrollment period</th>
524
                    <th scope="col">Enrollment period</th>
525
                    <th scope="col">Password expiration</th>
520
                    <th scope="col">Age required</th>
526
                    <th scope="col">Age required</th>
521
                    <th scope="col">Upper age limit</th>
527
                    <th scope="col">Upper age limit</th>
522
                    <th scope="col">Enrollment fee</th>
528
                    <th scope="col">Enrollment fee</th>
Lines 559-564 Link Here
559
                                until [% category.enrolmentperioddate | $KohaDates %]
565
                                until [% category.enrolmentperioddate | $KohaDates %]
560
                            [% END %]
566
                            [% END %]
561
                        </td>
567
                        </td>
568
                        [% IF (category.password_expiry_days) %]
569
                            <td>[% category.password_expiry_days | html %] days</td>
570
                        [% ELSE %]
571
                            <td>-</td>
572
                        [% END %]
562
                        [% IF (category.dateofbirthrequired) %]
573
                        [% IF (category.dateofbirthrequired) %]
563
                            <td>[% category.dateofbirthrequired | html %] years</td>
574
                            <td>[% category.dateofbirthrequired | html %] years</td>
564
                        [% ELSE %]
575
                        [% ELSE %]
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/auth.tt (+7 lines)
Lines 49-54 Link Here
49
    [% IF Categories.can_any_reset_password && Koha.Preference('OpacBaseURL') %]
49
    [% IF Categories.can_any_reset_password && Koha.Preference('OpacBaseURL') %]
50
        <a href="[% Koha.Preference('OpacBaseURL') | url %]/cgi-bin/koha/opac-password-recovery.pl">You must reset your password</a>.
50
        <a href="[% Koha.Preference('OpacBaseURL') | url %]/cgi-bin/koha/opac-password-recovery.pl">You must reset your password</a>.
51
    [% END %]
51
    [% END %]
52
[% ELSIF password_has_expired %]
53
    <div id="login_error"><strong>Error: </strong>Your password has expired!</div>
54
    [% IF Categories.can_any_reset_password && Koha.Preference('OpacBaseURL') %]
55
        <a href="[% Koha.Preference('OpacBaseURL') | url %]/cgi-bin/koha/opac-password-recovery.pl">You must reset your password</a>.
56
    [% ELSE %]
57
        <p>You must contact the library to have your password reset</p>
58
    [% END %]
52
[% ELSIF invalid_username_or_password %]
59
[% ELSIF invalid_username_or_password %]
53
<div id="login_error"><strong>Error: </strong>Invalid username or password</div>
60
<div id="login_error"><strong>Error: </strong>Invalid username or password</div>
54
[% END %]
61
[% END %]
(-)a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-auth.tt (-3 / +11 lines)
Lines 167-173 Link Here
167
                            [% END # /IF GoogleOpenIDConnect %]
167
                            [% END # /IF GoogleOpenIDConnect %]
168
                        [% END # /UNLESS OPACShibOnly %]
168
                        [% END # /UNLESS OPACShibOnly %]
169
169
170
                        [% IF !Koha.Preference('OPACShibOnly') or SCO_login or SCI_login %]
170
                        [% IF password_has_expired %]
171
                            <p class="error"><strong>Error: </strong>Your password has expired!</p>
172
                            [% IF Koha.Preference('OpacPasswordChange') && Categories.can_any_reset_password %]
173
                                <div id="resetpassword">
174
                                    <a href="/cgi-bin/koha/opac-password-recovery.pl">Reset your password?</a>
175
                                </div>
176
                            [% ELSE %]
177
                                <p>You must contact the library to reset your password</p>
178
                            [% END %]
179
                        [% ELSIF !Koha.Preference('OPACShibOnly') or SCO_login or SCI_login %]
171
                            [% IF SCO_login %]
180
                            [% IF SCO_login %]
172
                                <form action="/cgi-bin/koha/sco/sco-main.pl" name="auth" id="auth" method="post" autocomplete="off">
181
                                <form action="/cgi-bin/koha/sco/sco-main.pl" name="auth" id="auth" method="post" autocomplete="off">
173
                            [% ELSIF SCI_login %]
182
                            [% ELSIF SCI_login %]
Lines 217-223 Link Here
217
                                    [% END %]
226
                                    [% END %]
218
                                </div>
227
                                </div>
219
                            </form>
228
                            </form>
220
                        [% END # / IF !OPACShibOnly or SCO_login or SCI_login %]
229
                        [% END # / IF password_has_expired / ELSIF !OPACShibOnly or SCO_login or SCI_login %]
221
                    [% END # / IF loginprompt %]
230
                    [% END # / IF loginprompt %]
222
231
223
                    [% ELSE %]
232
                    [% ELSE %]
224
- 

Return to bug 29924