More work on circulation dialog. Adding files and styles necessary to do drop-shadow...
[koha.git] / C4 / Auth.pm
blob11e0615fc909c1f25fc93ab4942e48ef075a996b
1 # -*- tab-width: 8 -*-
2 # NOTE: This file uses 8-character tabs; do not change the tab size!
4 package C4::Auth;
6 # Copyright 2000-2002 Katipo Communications
8 # This file is part of Koha.
10 # Koha is free software; you can redistribute it and/or modify it under the
11 # terms of the GNU General Public License as published by the Free Software
12 # Foundation; either version 2 of the License, or (at your option) any later
13 # version.
15 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
16 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
17 # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License along with
20 # Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
21 # Suite 330, Boston, MA 02111-1307 USA
23 use strict;
24 use Digest::MD5 qw(md5_base64);
25 use CGI::Session;
27 require Exporter;
28 use C4::Context;
29 use C4::Output; # to get the template
30 use C4::Members;
31 use C4::Koha;
32 use C4::Branch; # GetBranches
34 # use utf8;
35 # use Net::LDAP;
36 # use Net::LDAP qw(:all);
38 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
40 # set the version for version checking
41 $VERSION = 3.00;
43 =head1 NAME
45 C4::Auth - Authenticates Koha users
47 =head1 SYNOPSIS
49 use CGI;
50 use C4::Auth;
52 my $query = new CGI;
54 my ($template, $borrowernumber, $cookie)
55 = get_template_and_user(
57 template_name => "opac-main.tmpl",
58 query => $query,
59 type => "opac",
60 authnotrequired => 1,
61 flagsrequired => {borrow => 1},
65 print $query->header(
66 -type => 'utf-8',
67 -cookie => $cookie
68 ), $template->output;
71 =head1 DESCRIPTION
73 The main function of this module is to provide
74 authentification. However the get_template_and_user function has
75 been provided so that a users login information is passed along
76 automatically. This gets loaded into the template.
78 =head1 FUNCTIONS
80 =over 2
82 =cut
84 @ISA = qw(Exporter);
85 @EXPORT = qw(
86 &checkauth
87 &get_template_and_user
90 =item get_template_and_user
92 my ($template, $borrowernumber, $cookie)
93 = get_template_and_user(
95 template_name => "opac-main.tmpl",
96 query => $query,
97 type => "opac",
98 authnotrequired => 1,
99 flagsrequired => {borrow => 1},
103 This call passes the C<query>, C<flagsrequired> and C<authnotrequired>
104 to C<&checkauth> (in this module) to perform authentification.
105 See C<&checkauth> for an explanation of these parameters.
107 The C<template_name> is then used to find the correct template for
108 the page. The authenticated users details are loaded onto the
109 template in the HTML::Template LOOP variable C<USER_INFO>. Also the
110 C<sessionID> is passed to the template. This can be used in templates
111 if cookies are disabled. It needs to be put as and input to every
112 authenticated page.
114 More information on the C<gettemplate> sub can be found in the
115 Output.pm module.
117 =cut
119 sub get_template_and_user {
120 my $in = shift;
121 my $template =
122 gettemplate( $in->{'template_name'}, $in->{'type'}, $in->{'query'} );
123 my ( $user, $cookie, $sessionID, $flags ) = checkauth(
124 $in->{'query'},
125 $in->{'authnotrequired'},
126 $in->{'flagsrequired'},
127 $in->{'type'}
128 ) unless ($in->{'template_name'}=~/maintenance/);
130 my $borrowernumber;
131 my $insecure = C4::Context->preference('insecure');
132 if ($user or $insecure) {
134 # load the template variables for stylesheets and JavaScript
135 $template->param( css_libs => $in->{'css_libs'} );
136 $template->param( css_module => $in->{'css_module'} );
137 $template->param( css_page => $in->{'css_page'} );
138 $template->param( css_widgets => $in->{'css_widgets'} );
140 $template->param( js_libs => $in->{'js_libs'} );
141 $template->param( js_module => $in->{'js_module'} );
142 $template->param( js_page => $in->{'js_page'} );
143 $template->param( js_widgets => $in->{'js_widgets'} );
145 # user info
146 $template->param( loggedinusername => $user );
147 $template->param( sessionID => $sessionID );
149 $borrowernumber = getborrowernumber($user);
150 my ( $borr, $alternativeflags ) =
151 GetMemberDetails( $borrowernumber );
152 my @bordat;
153 $bordat[0] = $borr;
154 $template->param( "USER_INFO" => \@bordat );
156 # We are going to use the $flags returned by checkauth
157 # to create the template's parameters that will indicate
158 # which menus the user can access.
159 if (( $flags && $flags->{superlibrarian}==1) or $insecure==1) {
160 $template->param( CAN_user_circulate => 1 );
161 $template->param( CAN_user_catalogue => 1 );
162 $template->param( CAN_user_parameters => 1 );
163 $template->param( CAN_user_borrowers => 1 );
164 $template->param( CAN_user_permission => 1 );
165 $template->param( CAN_user_reserveforothers => 1 );
166 $template->param( CAN_user_borrow => 1 );
167 $template->param( CAN_user_editcatalogue => 1 );
168 $template->param( CAN_user_updatecharge => 1 );
169 $template->param( CAN_user_acquisition => 1 );
170 $template->param( CAN_user_management => 1 );
171 $template->param( CAN_user_tools => 1 );
172 $template->param( CAN_user_editauthorities => 1 );
173 $template->param( CAN_user_serials => 1 );
174 $template->param( CAN_user_reports => 1 );
177 if ( $flags && $flags->{circulate} == 1 ) {
178 $template->param( CAN_user_circulate => 1 );
181 if ( $flags && $flags->{catalogue} == 1 ) {
182 $template->param( CAN_user_catalogue => 1 );
185 if ( $flags && $flags->{parameters} == 1 ) {
186 $template->param( CAN_user_parameters => 1 );
187 $template->param( CAN_user_management => 1 );
190 if ( $flags && $flags->{borrowers} == 1 ) {
191 $template->param( CAN_user_borrowers => 1 );
194 if ( $flags && $flags->{permissions} == 1 ) {
195 $template->param( CAN_user_permission => 1 );
198 if ( $flags && $flags->{reserveforothers} == 1 ) {
199 $template->param( CAN_user_reserveforothers => 1 );
202 if ( $flags && $flags->{borrow} == 1 ) {
203 $template->param( CAN_user_borrow => 1 );
206 if ( $flags && $flags->{editcatalogue} == 1 ) {
207 $template->param( CAN_user_editcatalogue => 1 );
210 if ( $flags && $flags->{updatecharges} == 1 ) {
211 $template->param( CAN_user_updatecharge => 1 );
214 if ( $flags && $flags->{acquisition} == 1 ) {
215 $template->param( CAN_user_acquisition => 1 );
218 if ( $flags && $flags->{tools} == 1 ) {
219 $template->param( CAN_user_tools => 1 );
222 if ( $flags && $flags->{editauthorities} == 1 ) {
223 $template->param( CAN_user_editauthorities => 1 );
226 if ( $flags && $flags->{serials} == 1 ) {
227 $template->param( CAN_user_serials => 1 );
230 if ( $flags && $flags->{reports} == 1 ) {
231 $template->param( CAN_user_reports => 1 );
234 if ( $in->{'type'} eq "intranet" ) {
235 $template->param(
236 intranetcolorstylesheet => C4::Context->preference("intranetcolorstylesheet"),
237 intranetstylesheet => C4::Context->preference("intranetstylesheet"),
238 IntranetNav => C4::Context->preference("IntranetNav"),
239 intranetuserjs => C4::Context->preference("intranetuserjs"),
240 TemplateEncoding => C4::Context->preference("TemplateEncoding"),
241 AmazonContent => C4::Context->preference("AmazonContent"),
242 LibraryName => C4::Context->preference("LibraryName"),
243 LoginBranchcode => (C4::Context->userenv?C4::Context->userenv->{"branch"}:"insecure"),
244 LoginBranchname => (C4::Context->userenv?C4::Context->userenv->{"branchname"}:"insecure"),
245 LoginFirstname => (C4::Context->userenv?C4::Context->userenv->{"firstname"}:"Bel"),
246 LoginSurname => C4::Context->userenv?C4::Context->userenv->{"surname"}:"Inconnu",
247 AutoLocation => C4::Context->preference("AutoLocation"),
248 hide_marc => C4::Context->preference("hide_marc"),
249 patronimages => C4::Context->preference("patronimages"),
250 "BiblioDefaultView".C4::Context->preference("IntranetBiblioDefaultView") => 1,
251 advancedMARCEditor => C4::Context->preference("advancedMARCEditor"),
252 suggestion => C4::Context->preference("suggestion"),
253 virtualshelves => C4::Context->preference("virtualshelves"),
254 LibraryName => C4::Context->preference("LibraryName"),
255 KohaAdminEmailAddress => "" . C4::Context->preference("KohaAdminEmailAddress"),
256 IntranetmainUserblock => C4::Context->preference("IntranetmainUserblock"),
257 IndependantBranches => C4::Context->preference("IndependantBranches"),
260 else {
261 warn "template type should be OPAC, here it is=[" . $in->{'type'} . "]" unless ( $in->{'type'} eq 'opac' );
262 my $LibraryNameTitle = C4::Context->preference("LibraryName");
263 $LibraryNameTitle =~ s/<(?:\/?)(?:br|p)\s*(?:\/?)>/ /sgi;
264 $LibraryNameTitle =~ s/<(?:[^<>'"]|'(?:[^']*)'|"(?:[^"]*)")*>//sg;
265 $template->param(
266 KohaAdminEmailAddress => "" . C4::Context->preference("KohaAdminEmailAddress"),
267 suggestion => "" . C4::Context->preference("suggestion"),
268 virtualshelves => "" . C4::Context->preference("virtualshelves"),
269 OpacNav => "" . C4::Context->preference("OpacNav"),
270 opacheader => "" . C4::Context->preference("opacheader"),
271 opaccredits => "" . C4::Context->preference("opaccredits"),
272 opacsmallimage => "" . C4::Context->preference("opacsmallimage"),
273 opaclargeimage => "" . C4::Context->preference("opaclargeimage"),
274 opaclayoutstylesheet => "". C4::Context->preference("opaclayoutstylesheet"),
275 opaccolorstylesheet => "". C4::Context->preference("opaccolorstylesheet"),
276 opaclanguagesdisplay => "". C4::Context->preference("opaclanguagesdisplay"),
277 opacuserlogin => "" . C4::Context->preference("opacuserlogin"),
278 opacbookbag => "" . C4::Context->preference("opacbookbag"),
279 TemplateEncoding => "". C4::Context->preference("TemplateEncoding"),
280 AmazonContent => "" . C4::Context->preference("AmazonContent"),
281 LibraryName => "" . C4::Context->preference("LibraryName"),
282 LibraryNameTitle => "" . $LibraryNameTitle,
283 LoginBranchcode => (C4::Context->userenv?C4::Context->userenv->{"branch"}:"insecure"),
284 LoginBranchname => C4::Context->userenv?C4::Context->userenv->{"branchname"}:"",
285 LoginFirstname => (C4::Context->userenv?C4::Context->userenv->{"firstname"}:"Bel"),
286 LoginSurname => C4::Context->userenv?C4::Context->userenv->{"surname"}:"Inconnu",
287 OpacPasswordChange => C4::Context->preference("OpacPasswordChange"),
288 opacreadinghistory => C4::Context->preference("opacreadinghistory"),
289 opacuserjs => C4::Context->preference("opacuserjs"),
290 OpacCloud => C4::Context->preference("OpacCloud"),
291 OpacTopissue => C4::Context->preference("OpacTopissue"),
292 OpacAuthorities => C4::Context->preference("OpacAuthorities"),
293 OpacBrowser => C4::Context->preference("OpacBrowser"),
294 RequestOnOpac => C4::Context->preference("RequestOnOpac"),
295 reviewson => C4::Context->preference("reviewson"),
296 hide_marc => C4::Context->preference("hide_marc"),
297 patronimages => C4::Context->preference("patronimages"),
298 mylibraryfirst => C4::Context->preference("SearchMyLibraryFirst"),
299 "BiblioDefaultView".C4::Context->preference("BiblioDefaultView") => 1,
302 return ( $template, $borrowernumber, $cookie );
305 =item checkauth
307 ($userid, $cookie, $sessionID) = &checkauth($query, $noauth, $flagsrequired, $type);
309 Verifies that the user is authorized to run this script. If
310 the user is authorized, a (userid, cookie, session-id, flags)
311 quadruple is returned. If the user is not authorized but does
312 not have the required privilege (see $flagsrequired below), it
313 displays an error page and exits. Otherwise, it displays the
314 login page and exits.
316 Note that C<&checkauth> will return if and only if the user
317 is authorized, so it should be called early on, before any
318 unfinished operations (e.g., if you've opened a file, then
319 C<&checkauth> won't close it for you).
321 C<$query> is the CGI object for the script calling C<&checkauth>.
323 The C<$noauth> argument is optional. If it is set, then no
324 authorization is required for the script.
326 C<&checkauth> fetches user and session information from C<$query> and
327 ensures that the user is authorized to run scripts that require
328 authorization.
330 The C<$flagsrequired> argument specifies the required privileges
331 the user must have if the username and password are correct.
332 It should be specified as a reference-to-hash; keys in the hash
333 should be the "flags" for the user, as specified in the Members
334 intranet module. Any key specified must correspond to a "flag"
335 in the userflags table. E.g., { circulate => 1 } would specify
336 that the user must have the "circulate" privilege in order to
337 proceed. To make sure that access control is correct, the
338 C<$flagsrequired> parameter must be specified correctly.
340 The C<$type> argument specifies whether the template should be
341 retrieved from the opac or intranet directory tree. "opac" is
342 assumed if it is not specified; however, if C<$type> is specified,
343 "intranet" is assumed if it is not "opac".
345 If C<$query> does not have a valid session ID associated with it
346 (i.e., the user has not logged in) or if the session has expired,
347 C<&checkauth> presents the user with a login page (from the point of
348 view of the original script, C<&checkauth> does not return). Once the
349 user has authenticated, C<&checkauth> restarts the original script
350 (this time, C<&checkauth> returns).
352 The login page is provided using a HTML::Template, which is set in the
353 systempreferences table or at the top of this file. The variable C<$type>
354 selects which template to use, either the opac or the intranet
355 authentification template.
357 C<&checkauth> returns a user ID, a cookie, and a session ID. The
358 cookie should be sent back to the browser; it verifies that the user
359 has authenticated.
361 =cut
363 sub checkauth {
364 my $query = shift;
365 # warn "Checking Auth";
366 # $authnotrequired will be set for scripts which will run without authentication
367 my $authnotrequired = shift;
368 my $flagsrequired = shift;
369 my $type = shift;
370 $type = 'opac' unless $type;
372 my $dbh = C4::Context->dbh;
373 my $timeout = C4::Context->preference('timeout');
374 $timeout = 600 unless $timeout;
377 # If Version syspref is unavailable, it means Koha is beeing installed,
378 # and so we must redirect to OPAC maintenance page or to the WebInstaller
379 #warn "about to check version";
380 unless (C4::Context->preference('Version')) {
381 if ($type ne 'opac') {
382 warn "Install required, redirecting to Installer";
383 print $query->redirect("/cgi-bin/koha/installer/install.pl");
385 else {
386 warn "OPAC Install required, redirecting to maintenance";
387 print $query->redirect("/cgi-bin/koha/maintenance.pl");
389 exit;
393 # state variables
394 my $loggedin = 0;
395 my %info;
396 my ( $userid, $cookie, $sessionID, $flags );
397 my $logout = $query->param('logout.x');
398 if ( $userid = $ENV{'REMOTE_USER'} ) {
399 # Using Basic Authentication, no cookies required
400 $cookie = $query->cookie(
401 -name => 'CGISESSID',
402 -value => '',
403 -expires => ''
405 $loggedin = 1;
407 elsif ( $sessionID = $query->cookie("CGISESSID")) {
408 my $storage_method = C4::Context->preference('SessionStorage');
409 my $session;
410 if ($storage_method eq 'mysql'){
411 $session = new CGI::Session("driver:MySQL", $sessionID, {Handle=>$dbh});
413 else {
414 # catch all defaults to tmp should work on all systems
415 $session = new CGI::Session("driver:File", $sessionID, {Directory=>'/tmp'});
417 C4::Context->_new_userenv($sessionID);
418 if ($session){
419 C4::Context::set_userenv(
420 $session->param('number'), $session->param('id'),
421 $session->param('cardnumber'), $session->param('firstname'),
422 $session->param('surname'), $session->param('branch'),
423 $session->param('branchname'), $session->param('flags'),
424 $session->param('emailaddress'), $session->param('branchprinter')
426 # warn "".$session->param('cardnumber').", ".$session->param('firstname').",
427 # ".$session->param('surname').", ".$session->param('branch');
429 my $ip;
430 my $lasttime;
431 if ($session) {
432 $ip = $session->param('ip');
433 $lasttime = $session->param('lasttime');
434 $userid = $session->param('id');
438 if ($logout) {
440 # voluntary logout the user
442 $session->flush;
443 $session->delete();
444 C4::Context->_unset_userenv($sessionID);
445 $sessionID = undef;
446 $userid = undef;
447 open L, ">>/tmp/sessionlog";
448 my $time = localtime( time() );
449 printf L "%20s from %16s logged out at %30s (manually).\n", $userid,
450 $ip, $time;
451 close L;
453 if ($userid) {
454 if ( $lasttime < time() - $timeout ) {
455 # timed logout
456 $info{'timed_out'} = 1;
457 $session->delete();
458 C4::Context->_unset_userenv($sessionID);
459 $userid = undef;
460 $sessionID = undef;
461 open L, ">>/tmp/sessionlog";
462 my $time = localtime( time() );
463 printf L "%20s from %16s logged out at %30s (inactivity).\n",
464 $userid, $ip, $time;
465 close L;
467 elsif ( $ip ne $ENV{'REMOTE_ADDR'} ) {
468 # Different ip than originally logged in from
469 $info{'oldip'} = $ip;
470 $info{'newip'} = $ENV{'REMOTE_ADDR'};
471 $info{'different_ip'} = 1;
472 $session->delete();
473 C4::Context->_unset_userenv($sessionID);
474 $sessionID = undef;
475 $userid = undef;
476 open L, ">>/tmp/sessionlog";
477 my $time = localtime( time() );
478 printf L
479 "%20s from logged out at %30s (ip changed from %16s to %16s).\n",
480 $userid, $time, $ip, $info{'newip'};
481 close L;
483 else {
484 $cookie = $query->cookie( CGISESSID => $session->id );
485 $session->param('lasttime',time());
486 $flags = haspermission( $dbh, $userid, $flagsrequired );
487 if ($flags) {
488 $loggedin = 1;
490 else {
491 $info{'nopermission'} = 1;
496 unless ($userid) {
497 my $storage_method = C4::Context->preference('SessionStorage');
498 my $session;
499 if ($storage_method eq 'mysql'){
500 $session = new CGI::Session("driver:MySQL", $sessionID, {Handle=>$dbh});
502 else {
503 # catch all defaults to tmp should work on all systems
504 $session = new CGI::Session("driver:File", $sessionID, {Directory=>'/tmp'});
507 my $sessionID;
508 if ($session) {
509 $sessionID = $session->id;
511 $userid = $query->param('userid');
512 C4::Context->_new_userenv($sessionID);
513 my $password = $query->param('password');
514 C4::Context->_new_userenv($sessionID);
515 my ( $return, $cardnumber ) = checkpw( $dbh, $userid, $password );
516 if ($return) {
517 open L, ">>/tmp/sessionlog";
518 my $time = localtime( time() );
519 printf L "%20s from %16s logged in at %30s.\n", $userid,
520 $ENV{'REMOTE_ADDR'}, $time;
521 close L;
522 $cookie = $query->cookie(CGISESSID => $sessionID);
523 if ( $flags = haspermission( $dbh, $userid, $flagsrequired ) ) {
524 $loggedin = 1;
526 else {
527 $info{'nopermission'} = 1;
528 C4::Context->_unset_userenv($sessionID);
530 if ( $return == 1 ) {
531 my (
532 $borrowernumber, $firstname, $surname,
533 $userflags, $branchcode, $branchname,
534 $branchprinter, $emailaddress
536 my $sth =
537 $dbh->prepare(
538 "select borrowernumber, firstname, surname, flags, borrowers.branchcode, branches.branchname as branchname,branches.branchprinter as branchprinter, email from borrowers left join branches on borrowers.branchcode=branches.branchcode where userid=?"
540 $sth->execute($userid);
542 $borrowernumber, $firstname, $surname,
543 $userflags, $branchcode, $branchname,
544 $branchprinter, $emailaddress
546 = $sth->fetchrow
547 if ( $sth->rows );
549 # warn "$cardnumber,$borrowernumber,$userid,$firstname,$surname,$userflags,$branchcode,$emailaddress";
550 unless ( $sth->rows ) {
551 my $sth =
552 $dbh->prepare(
553 "select borrowernumber, firstname, surname, flags, borrowers.branchcode, branches.branchname as branchname, branches.branchprinter as branchprinter, email from borrowers left join branches on borrowers.branchcode=branches.branchcode where cardnumber=?"
555 $sth->execute($cardnumber);
557 $borrowernumber, $firstname, $surname,
558 $userflags, $branchcode, $branchname,
559 $branchprinter, $emailaddress
561 = $sth->fetchrow
562 if ( $sth->rows );
564 # warn "$cardnumber,$borrowernumber,$userid,$firstname,$surname,$userflags,$branchcode,$emailaddress";
565 unless ( $sth->rows ) {
566 $sth->execute($userid);
568 $borrowernumber, $firstname, $surname, $userflags,
569 $branchcode, $branchname, $branchprinter, $emailaddress
571 = $sth->fetchrow
572 if ( $sth->rows );
576 # launch a sequence to check if we have a ip for the branch, if we have one we replace the branchcode of the userenv by the branch bound in the ip.
577 my $ip = $ENV{'REMOTE_ADDR'};
578 # if they specify at login, use that
579 if ($query->param('branch')) {
580 $branchcode = $query->param('branch');
581 $branchname = GetBranchName($branchcode);
583 my $branches = GetBranches();
584 my @branchesloop;
585 foreach my $br ( keys %$branches ) {
586 # now we work with the treatment of ip
587 my $domain = $branches->{$br}->{'branchip'};
588 if ( $domain && $ip =~ /^$domain/ ) {
589 $branchcode = $branches->{$br}->{'branchcode'};
591 # new op dev : add the branchprinter and branchname in the cookie
592 $branchprinter = $branches->{$br}->{'branchprinter'};
593 $branchname = $branches->{$br}->{'branchname'};
596 $session->param('number',$borrowernumber);
597 $session->param('id',$userid);
598 $session->param('cardnumber',$cardnumber);
599 $session->param('firstname',$firstname);
600 $session->param('surname',$surname);
601 $session->param('branch',$branchcode);
602 $session->param('branchname',$branchname);
603 $session->param('flags',$userflags);
604 $session->param('emailaddress',$emailaddress);
605 $session->param('ip',$session->remote_addr());
606 $session->param('lasttime',time());
607 # warn "".$session->param('cardnumber').", ".$session->param('firstname').",
608 # ".$session->param('surname').", ".$session->param('branch');
610 elsif ( $return == 2 ) {
611 #We suppose the user is the superlibrarian
612 $session->param('number',0);
613 $session->param('id',C4::Context->config('user'));
614 $session->param('cardnumber',C4::Context->config('user'));
615 $session->param('firstname',C4::Context->config('user'));
616 $session->param('surname',C4::Context->config('user'));
617 $session->param('branch','NO_LIBRARY_SET');
618 $session->param('branchname','NO_LIBRARY_SET');
619 $session->param('flags',1);
620 $session->param('emailaddress', C4::Context->preference('KohaAdminEmailAddress'));
621 $session->param('ip',$session->remote_addr());
622 $session->param('lasttime',time());
624 if ($session){
625 C4::Context::set_userenv(
626 $session->param('number'), $session->param('id'),
627 $session->param('cardnumber'), $session->param('firstname'),
628 $session->param('surname'), $session->param('branch'),
629 $session->param('branchname'), $session->param('flags'),
630 $session->param('emailaddress'), $session->param('branchprinter')
635 else {
636 if ($userid) {
637 $info{'invalid_username_or_password'} = 1;
638 C4::Context->_unset_userenv($sessionID);
642 my $insecure = C4::Context->boolean_preference('insecure');
644 # finished authentification, now respond
645 if ( $loggedin || $authnotrequired || ( defined($insecure) && $insecure ) )
647 # successful login
648 unless ($cookie) {
649 $cookie = $query->cookie( CGISESSID => ''
652 return ( $userid, $cookie, $sessionID, $flags );
658 # AUTH rejected, show the login/password template, after checking the DB.
662 # get the inputs from the incoming query
663 my @inputs = ();
664 foreach my $name ( param $query) {
665 (next) if ( $name eq 'userid' || $name eq 'password' );
666 my $value = $query->param($name);
667 push @inputs, { name => $name, value => $value };
669 # get the branchloop, which we need for authentication
670 my $branches = GetBranches();
671 my @branch_loop;
672 for my $branch_hash (keys %$branches) {
673 push @branch_loop, {branchcode => "$branch_hash", branchname => $branches->{$branch_hash}->{'branchname'}, };
676 # check that database and koha version are the same
677 # there is no DB version, it's a fresh install,
678 # go to web installer
679 # there is a DB version, compare it to the code version
680 my $kohaversion=C4::Context::KOHAVERSION;
681 # remove the 3 last . to have a Perl number
682 $kohaversion =~ s/(.*\..*)\.(.*)\.(.*)/$1$2$3/;
683 # warn "kohaversion : $kohaversion";
684 if (C4::Context->preference('Version') < $kohaversion){
685 if ($type ne 'opac'){
686 warn "Database update needed, redirecting to Installer. Database is ".C4::Context->preference('Version')." and Koha is : ".C4::Context->config("kohaversion");
687 print $query->redirect("/cgi-bin/koha/installer/install.pl?step=3");
688 } else {
689 warn "OPAC :Database update needed, redirecting to maintenance. Database is ".C4::Context->preference('Version')." and Koha is : ".C4::Context->config("kohaversion");
690 print $query->redirect("/cgi-bin/koha/maintenance.pl");
692 exit;
694 my $template_name;
695 if ( $type eq 'opac' ) {
696 $template_name = "opac-auth.tmpl";
698 else {
699 $template_name = "auth.tmpl";
701 my $template = gettemplate( $template_name, $type, $query );
702 $template->param(branchloop => \@branch_loop,);
703 $template->param(
704 login => 1,
705 INPUTS => \@inputs,
706 suggestion => C4::Context->preference("suggestion"),
707 virtualshelves => C4::Context->preference("virtualshelves"),
708 opaclargeimage => C4::Context->preference("opaclargeimage"),
709 LibraryName => C4::Context->preference("LibraryName"),
710 OpacNav => C4::Context->preference("OpacNav"),
711 opaccredits => C4::Context->preference("opaccredits"),
712 opacreadinghistory => C4::Context->preference("opacreadinghistory"),
713 opacsmallimage => C4::Context->preference("opacsmallimage"),
714 opaclayoutstylesheet => C4::Context->preference("opaclayoutstylesheet"),
715 opaccolorstylesheet => C4::Context->preference("opaccolorstylesheet"),
716 opaclanguagesdisplay => C4::Context->preference("opaclanguagesdisplay"),
717 opacuserjs => C4::Context->preference("opacuserjs"),
719 intranetcolorstylesheet =>
720 C4::Context->preference("intranetcolorstylesheet"),
721 intranetstylesheet => C4::Context->preference("intranetstylesheet"),
722 IntranetNav => C4::Context->preference("IntranetNav"),
723 intranetuserjs => C4::Context->preference("intranetuserjs"),
724 TemplateEncoding => C4::Context->preference("TemplateEncoding"),
725 IndependantBranches => C4::Context->preference("IndependantBranches"),
727 $template->param( loginprompt => 1 ) unless $info{'nopermission'};
729 my $self_url = $query->url( -absolute => 1 );
730 $template->param(
731 url => $self_url,
732 LibraryName => => C4::Context->preference("LibraryName"),
734 $template->param( \%info );
735 # $cookie = $query->cookie(CGISESSID => $session->id
736 # );
737 print $query->header(
738 -type => 'text/html',
739 -charset => 'utf-8',
740 -cookie => $cookie
742 $template->output;
743 exit;
746 sub checkpw {
748 my ( $dbh, $userid, $password ) = @_;
750 # INTERNAL AUTH
751 my $sth =
752 $dbh->prepare(
753 "select password,cardnumber,borrowernumber,userid,firstname,surname,branchcode,flags from borrowers where userid=?"
755 $sth->execute($userid);
756 if ( $sth->rows ) {
757 my ( $md5password, $cardnumber, $borrowernumber, $userid, $firstname,
758 $surname, $branchcode, $flags )
759 = $sth->fetchrow;
760 if ( md5_base64($password) eq $md5password ) {
762 C4::Context->set_userenv( "$borrowernumber", $userid, $cardnumber,
763 $firstname, $surname, $branchcode, $flags );
764 return 1, $cardnumber;
767 $sth =
768 $dbh->prepare(
769 "select password,cardnumber,borrowernumber,userid, firstname,surname,branchcode,flags from borrowers where cardnumber=?"
771 $sth->execute($userid);
772 if ( $sth->rows ) {
773 my ( $md5password, $cardnumber, $borrowernumber, $userid, $firstname,
774 $surname, $branchcode, $flags )
775 = $sth->fetchrow;
776 if ( md5_base64($password) eq $md5password ) {
778 C4::Context->set_userenv( $borrowernumber, $userid, $cardnumber,
779 $firstname, $surname, $branchcode, $flags );
780 return 1, $userid;
783 if ( $userid && $userid eq C4::Context->config('user')
784 && "$password" eq C4::Context->config('pass') )
787 # Koha superuser account
788 # C4::Context->set_userenv(0,0,C4::Context->config('user'),C4::Context->config('user'),C4::Context->config('user'),"",1);
789 return 2;
791 if ( $userid && $userid eq 'demo'
792 && "$password" eq 'demo'
793 && C4::Context->config('demo') )
796 # DEMO => the demo user is allowed to do everything (if demo set to 1 in koha.conf
797 # some features won't be effective : modify systempref, modify MARC structure,
798 return 2;
800 return 0;
803 sub getuserflags {
804 my $cardnumber = shift;
805 my $dbh = shift;
806 my $userflags;
807 my $sth = $dbh->prepare("SELECT flags FROM borrowers WHERE cardnumber=?");
808 $sth->execute($cardnumber);
809 my ($flags) = $sth->fetchrow;
810 $flags = 0 unless $flags;
811 $sth = $dbh->prepare("SELECT bit, flag, defaulton FROM userflags");
812 $sth->execute;
814 while ( my ( $bit, $flag, $defaulton ) = $sth->fetchrow ) {
815 if ( ( $flags & ( 2**$bit ) ) || $defaulton ) {
816 $userflags->{$flag} = 1;
818 else {
819 $userflags->{$flag} = 0;
822 return $userflags;
825 sub haspermission {
826 my ( $dbh, $userid, $flagsrequired ) = @_;
827 my $sth = $dbh->prepare("SELECT cardnumber FROM borrowers WHERE userid=?");
828 $sth->execute($userid);
829 my ($cardnumber) = $sth->fetchrow;
830 ($cardnumber) || ( $cardnumber = $userid );
831 my $flags = getuserflags( $cardnumber, $dbh );
832 my $configfile;
833 if ( $userid eq C4::Context->config('user') ) {
835 # Super User Account from /etc/koha.conf
836 $flags->{'superlibrarian'} = 1;
838 if ( $userid eq 'demo' && C4::Context->config('demo') ) {
840 # Demo user that can do "anything" (demo=1 in /etc/koha.conf)
841 $flags->{'superlibrarian'} = 1;
843 return $flags if $flags->{superlibrarian};
844 foreach ( keys %$flagsrequired ) {
845 return $flags if $flags->{$_};
847 return 0;
850 sub getborrowernumber {
851 my ($userid) = @_;
852 my $dbh = C4::Context->dbh;
853 for my $field ( 'userid', 'cardnumber' ) {
854 my $sth =
855 $dbh->prepare("select borrowernumber from borrowers where $field=?");
856 $sth->execute($userid);
857 if ( $sth->rows ) {
858 my ($bnumber) = $sth->fetchrow;
859 return $bnumber;
862 return 0;
865 END { } # module clean-up code here (global destructor)
867 __END__
869 =back
871 =head1 SEE ALSO
873 CGI(3)
875 C4::Output(3)
877 Digest::MD5(3)
879 =cut