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

(-)a/C4/Auth.pm (-3 / +9 lines)
Lines 948-953 sub checkauth { Link Here
948
                $info{oldip}        = $more_info->{old_ip};
948
                $info{oldip}        = $more_info->{old_ip};
949
                $info{newip}        = $more_info->{new_ip};
949
                $info{newip}        = $more_info->{new_ip};
950
                $info{different_ip} = 1;
950
                $info{different_ip} = 1;
951
            } elsif ( $return eq 'password_expired' ) {
952
                $info{password_has_expired} = 1;
951
            }
953
            }
952
        }
954
        }
953
    }
955
    }
Lines 1339-1345 sub checkauth { Link Here
1339
        PatronSelfRegistration                => C4::Context->preference("PatronSelfRegistration"),
1341
        PatronSelfRegistration                => C4::Context->preference("PatronSelfRegistration"),
1340
        PatronSelfRegistrationDefaultCategory => C4::Context->preference("PatronSelfRegistrationDefaultCategory"),
1342
        PatronSelfRegistrationDefaultCategory => C4::Context->preference("PatronSelfRegistrationDefaultCategory"),
1341
        opac_css_override                     => $ENV{'OPAC_CSS_OVERRIDE'},
1343
        opac_css_override                     => $ENV{'OPAC_CSS_OVERRIDE'},
1342
        too_many_login_attempts               => ( $patron and $patron->account_locked )
1344
        too_many_login_attempts               => ( $patron and $patron->account_locked ),
1345
        password_has_expired                  => ( $patron and $patron->password_expired )
1343
    );
1346
    );
1344
1347
1345
    $template->param( SCO_login => 1 ) if ( $query->param('sco_user_login') );
1348
    $template->param( SCO_login => 1 ) if ( $query->param('sco_user_login') );
Lines 1716-1721 sub check_cookie_auth { Link Here
1716
1719
1717
        } elsif ( $userid ) {
1720
        } elsif ( $userid ) {
1718
            $session->param( 'lasttime', time() );
1721
            $session->param( 'lasttime', time() );
1722
            my $patron = Koha::Patrons->find({ userid => $userid });
1723
            $patron = Koha::Patron->find({ cardnumber => $userid }) unless $patron;
1724
            return ("password_expired", undef ) if $patron->password_expired;
1719
            my $flags = defined($flagsrequired) ? haspermission( $userid, $flagsrequired ) : 1;
1725
            my $flags = defined($flagsrequired) ? haspermission( $userid, $flagsrequired ) : 1;
1720
            if ($flags) {
1726
            if ($flags) {
1721
                C4::Context->_new_userenv($sessionID);
1727
                C4::Context->_new_userenv($sessionID);
Lines 1824-1831 sub checkpw { Link Here
1824
    # 0 if auth is nok
1830
    # 0 if auth is nok
1825
    # -1 if user bind failed (LDAP only)
1831
    # -1 if user bind failed (LDAP only)
1826
1832
1827
    if ( $patron and $patron->account_locked ) {
1833
    if ( $patron and ( $patron->account_locked || $patron->password_expired )  ) {
1828
        # Nothing to check, account is locked
1834
        # Nothing to check, account is locked or password expired
1829
    } elsif ($ldap && defined($password)) {
1835
    } elsif ($ldap && defined($password)) {
1830
        my ( $retval, $retcard, $retuserid ) = checkpw_ldap(@_);    # EXTERNAL AUTH
1836
        my ( $retval, $retcard, $retuserid ) = checkpw_ldap(@_);    # EXTERNAL AUTH
1831
        if ( $retval == 1 ) {
1837
        if ( $retval == 1 ) {
(-)a/Koha/Patron.pm (+20 lines)
Lines 266-271 sub store { Link Here
266
                # Make a copy of the plain text password for later use
266
                # Make a copy of the plain text password for later use
267
                $self->plain_text_password( $self->password );
267
                $self->plain_text_password( $self->password );
268
268
269
                $self->password_expiration_date( $self->password
270
                    ? $self->category->get_password_expiry_date
271
                    : undef );
269
                # Create a disabled account if no password provided
272
                # Create a disabled account if no password provided
270
                $self->password( $self->password
273
                $self->password( $self->password
271
                    ? Koha::AuthUtils::hash_password( $self->password )
274
                    ? Koha::AuthUtils::hash_password( $self->password )
Lines 779-784 sub is_expired { Link Here
779
    return 0;
782
    return 0;
780
}
783
}
781
784
785
=head3 password_expired
786
787
my $password_expired = $patron->password_expired;
788
789
Returns 1 if the patron's password is expired or 0;
790
791
=cut
792
793
sub password_expired {
794
    my ($self) = @_;
795
    return 0 unless $self->password_expiration_date;
796
    return 1 if dt_from_string( $self->password_expiration_date ) < dt_from_string->truncate( to => 'day' );
797
    return 0;
798
}
799
782
=head3 is_going_to_expire
800
=head3 is_going_to_expire
783
801
784
my $is_going_to_expire = $patron->is_going_to_expire;
802
my $is_going_to_expire = $patron->is_going_to_expire;
Lines 878-883 sub set_password { Link Here
878
896
879
    my $digest = Koha::AuthUtils::hash_password($password);
897
    my $digest = Koha::AuthUtils::hash_password($password);
880
898
899
    $self->password_expiration_date( $self->category->get_password_expiry_date );
900
881
    # We do not want to call $self->store and retrieve password from DB
901
    # We do not want to call $self->store and retrieve password from DB
882
    $self->password($digest);
902
    $self->password($digest);
883
    $self->login_attempts(0);
903
    $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