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

(-)a/C4/Auth.pm (-3 / +9 lines)
Lines 942-947 sub checkauth { Link Here
942
                $info{oldip}        = $more_info->{old_ip};
942
                $info{oldip}        = $more_info->{old_ip};
943
                $info{newip}        = $more_info->{new_ip};
943
                $info{newip}        = $more_info->{new_ip};
944
                $info{different_ip} = 1;
944
                $info{different_ip} = 1;
945
            } elsif ( $return eq 'password_expired' ) {
946
                $info{password_has_expired} = 1;
945
            }
947
            }
946
        }
948
        }
947
    }
949
    }
Lines 1333-1339 sub checkauth { Link Here
1333
        PatronSelfRegistration                => C4::Context->preference("PatronSelfRegistration"),
1335
        PatronSelfRegistration                => C4::Context->preference("PatronSelfRegistration"),
1334
        PatronSelfRegistrationDefaultCategory => C4::Context->preference("PatronSelfRegistrationDefaultCategory"),
1336
        PatronSelfRegistrationDefaultCategory => C4::Context->preference("PatronSelfRegistrationDefaultCategory"),
1335
        opac_css_override                     => $ENV{'OPAC_CSS_OVERRIDE'},
1337
        opac_css_override                     => $ENV{'OPAC_CSS_OVERRIDE'},
1336
        too_many_login_attempts               => ( $patron and $patron->account_locked )
1338
        too_many_login_attempts               => ( $patron and $patron->account_locked ),
1339
        password_has_expired                  => ( $patron and $patron->password_expired )
1337
    );
1340
    );
1338
1341
1339
    $template->param( SCO_login => 1 ) if ( $query->param('sco_user_login') );
1342
    $template->param( SCO_login => 1 ) if ( $query->param('sco_user_login') );
Lines 1723-1728 sub check_cookie_auth { Link Here
1723
            return ( "restricted", undef, { old_ip => $ip, new_ip => $remote_addr});
1726
            return ( "restricted", undef, { old_ip => $ip, new_ip => $remote_addr});
1724
        } elsif ( $userid ) {
1727
        } elsif ( $userid ) {
1725
            $session->param( 'lasttime', time() );
1728
            $session->param( 'lasttime', time() );
1729
            my $patron = Koha::Patrons->find({ userid => $userid });
1730
            $patron = Koha::Patron->find({ cardnumber => $userid }) unless $patron;
1731
            return ("password_expired", undef ) if $patron->password_expired;
1726
            my $flags = defined($flagsrequired) ? haspermission( $userid, $flagsrequired ) : 1;
1732
            my $flags = defined($flagsrequired) ? haspermission( $userid, $flagsrequired ) : 1;
1727
            if ($flags) {
1733
            if ($flags) {
1728
                return ( "ok", $session );
1734
                return ( "ok", $session );
Lines 1814-1821 sub checkpw { Link Here
1814
    # 0 if auth is nok
1820
    # 0 if auth is nok
1815
    # -1 if user bind failed (LDAP only)
1821
    # -1 if user bind failed (LDAP only)
1816
1822
1817
    if ( $patron and $patron->account_locked ) {
1823
    if ( $patron and ( $patron->account_locked || $patron->password_expired )  ) {
1818
        # Nothing to check, account is locked
1824
        # Nothing to check, account is locked or password expired
1819
    } elsif ($ldap && defined($password)) {
1825
    } elsif ($ldap && defined($password)) {
1820
        my ( $retval, $retcard, $retuserid ) = checkpw_ldap(@_);    # EXTERNAL AUTH
1826
        my ( $retval, $retcard, $retuserid ) = checkpw_ldap(@_);    # EXTERNAL AUTH
1821
        if ( $retval == 1 ) {
1827
        if ( $retval == 1 ) {
(-)a/Koha/Patron.pm (+20 lines)
Lines 265-270 sub store { Link Here
265
                # Make a copy of the plain text password for later use
265
                # Make a copy of the plain text password for later use
266
                $self->plain_text_password( $self->password );
266
                $self->plain_text_password( $self->password );
267
267
268
                $self->password_expiration_date( $self->password
269
                    ? $self->category->get_password_expiry_date
270
                    : undef );
268
                # Create a disabled account if no password provided
271
                # Create a disabled account if no password provided
269
                $self->password( $self->password
272
                $self->password( $self->password
270
                    ? Koha::AuthUtils::hash_password( $self->password )
273
                    ? Koha::AuthUtils::hash_password( $self->password )
Lines 778-783 sub is_expired { Link Here
778
    return 0;
781
    return 0;
779
}
782
}
780
783
784
=head3 password_expired
785
786
my $password_expired = $patron->password_expired;
787
788
Returns 1 if the patron's password is expired or 0;
789
790
=cut
791
792
sub password_expired {
793
    my ($self) = @_;
794
    return 0 unless $self->password_expiration_date;
795
    return 1 if dt_from_string( $self->password_expiration_date ) < dt_from_string->truncate( to => 'day' );
796
    return 0;
797
}
798
781
=head3 is_going_to_expire
799
=head3 is_going_to_expire
782
800
783
my $is_going_to_expire = $patron->is_going_to_expire;
801
my $is_going_to_expire = $patron->is_going_to_expire;
Lines 877-882 sub set_password { Link Here
877
895
878
    my $digest = Koha::AuthUtils::hash_password($password);
896
    my $digest = Koha::AuthUtils::hash_password($password);
879
897
898
    $self->password_expiration_date( $self->category->get_password_expiry_date );
899
880
    # We do not want to call $self->store and retrieve password from DB
900
    # We do not want to call $self->store and retrieve password from DB
881
    $self->password($digest);
901
    $self->password($digest);
882
    $self->login_attempts(0);
902
    $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 218-224 Link Here
218
                                    </div>
227
                                    </div>
219
                                [% END %]
228
                                [% END %]
220
                            </form>
229
                            </form>
221
                        [% END # / IF !OPACShibOnly or SCO_login or SCI_login %]
230
                        [% END # / IF password_has_expired / ELSIF !OPACShibOnly or SCO_login or SCI_login %]
222
                    [% END # / IF loginprompt %]
231
                    [% END # / IF loginprompt %]
223
232
224
                    [% ELSE %]
233
                    [% ELSE %]
225
- 

Return to bug 29924