Merge branch 'bug_9587' into 3.12-master

This commit is contained in:
Jared Camins-Esakov 2013-02-24 10:18:54 -05:00
commit 5f40f3f0e4
15 changed files with 528 additions and 134 deletions

View File

@ -38,8 +38,8 @@ use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $debug $ldap $cas $cas
BEGIN {
sub psgi_env { any { /^psgi\./ } keys %ENV }
sub safe_exit {
if ( psgi_env ) { die 'psgi:exit' }
else { exit }
if ( psgi_env ) { die 'psgi:exit' }
else { exit }
}
$VERSION = 3.07.00.049; # set version for version checking
@ -53,8 +53,8 @@ BEGIN {
$caslogout = C4::Context->preference('casLogout');
require C4::Auth_with_cas; # no import
if ($ldap) {
require C4::Auth_with_ldap;
import C4::Auth_with_ldap qw(checkpw_ldap);
require C4::Auth_with_ldap;
import C4::Auth_with_ldap qw(checkpw_ldap);
}
if ($cas) {
import C4::Auth_with_cas qw(check_api_auth_cas checkpw_cas login_cas logout_cas login_cas_url);
@ -234,34 +234,34 @@ sub get_template_and_user {
}
}
}
# Logged-in opac search history
# If the requested template is an opac one and opac search history is enabled
if ($in->{type} eq 'opac' && C4::Context->preference('EnableOpacSearchHistory')) {
my $dbh = C4::Context->dbh;
my $query = "SELECT COUNT(*) FROM search_history WHERE userid=?";
my $sth = $dbh->prepare($query);
$sth->execute($borrowernumber);
# If at least one search has already been performed
if ($sth->fetchrow_array > 0) {
# We show the link in opac
$template->param(ShowOpacRecentSearchLink => 1);
}
# Logged-in opac search history
# If the requested template is an opac one and opac search history is enabled
if ($in->{type} eq 'opac' && C4::Context->preference('EnableOpacSearchHistory')) {
my $dbh = C4::Context->dbh;
my $query = "SELECT COUNT(*) FROM search_history WHERE userid=?";
my $sth = $dbh->prepare($query);
$sth->execute($borrowernumber);
# And if there's a cookie with searches performed when the user was not logged in,
# we add them to the logged-in search history
my $searchcookie = $in->{'query'}->cookie('KohaOpacRecentSearches');
if ($searchcookie){
$searchcookie = uri_unescape($searchcookie);
my @recentSearches = @{thaw($searchcookie) || []};
if (@recentSearches) {
my $sth = $dbh->prepare($SEARCH_HISTORY_INSERT_SQL);
$sth->execute( $borrowernumber,
$in->{'query'}->cookie("CGISESSID"),
$_->{'query_desc'},
$_->{'query_cgi'},
$_->{'total'},
$_->{'time'},
# If at least one search has already been performed
if ($sth->fetchrow_array > 0) {
# We show the link in opac
$template->param(ShowOpacRecentSearchLink => 1);
}
# And if there's a cookie with searches performed when the user was not logged in,
# we add them to the logged-in search history
my $searchcookie = $in->{'query'}->cookie('KohaOpacRecentSearches');
if ($searchcookie){
$searchcookie = uri_unescape($searchcookie);
my @recentSearches = @{thaw($searchcookie) || []};
if (@recentSearches) {
my $sth = $dbh->prepare($SEARCH_HISTORY_INSERT_SQL);
$sth->execute( $borrowernumber,
$in->{'query'}->cookie("CGISESSID"),
$_->{'query_desc'},
$_->{'query_cgi'},
$_->{'total'},
$_->{'time'},
) foreach @recentSearches;
# And then, delete the cookie's content
@ -271,34 +271,34 @@ sub get_template_and_user {
-HttpOnly => 1,
-expires => ''
);
$cookie = [$cookie, $newsearchcookie];
}
}
}
$cookie = [$cookie, $newsearchcookie];
}
}
}
}
else { # if this is an anonymous session, setup to display public lists...
else { # if this is an anonymous session, setup to display public lists...
$template->param( sessionID => $sessionID );
my ($total, $pubshelves) = C4::VirtualShelves::GetSomeShelfNames(undef, 'MASTHEAD');
$template->param(
pubshelves => $total->{pubtotal},
pubshelvesloop => $pubshelves,
);
$template->param(
pubshelves => $total->{pubtotal},
pubshelvesloop => $pubshelves,
);
}
# Anonymous opac search history
# If opac search history is enabled and at least one search has already been performed
if (C4::Context->preference('EnableOpacSearchHistory')) {
my $searchcookie = $in->{'query'}->cookie('KohaOpacRecentSearches');
if ($searchcookie){
$searchcookie = uri_unescape($searchcookie);
my @recentSearches = @{thaw($searchcookie) || []};
# We show the link in opac
if (@recentSearches) {
$template->param(ShowOpacRecentSearchLink => 1);
}
}
}
# Anonymous opac search history
# If opac search history is enabled and at least one search has already been performed
if (C4::Context->preference('EnableOpacSearchHistory')) {
my $searchcookie = $in->{'query'}->cookie('KohaOpacRecentSearches');
if ($searchcookie){
$searchcookie = uri_unescape($searchcookie);
my @recentSearches = @{thaw($searchcookie) || []};
# We show the link in opac
if (@recentSearches) {
$template->param(ShowOpacRecentSearchLink => 1);
}
}
}
if(C4::Context->preference('dateformat')){
$template->param( dateformat => C4::Context->preference('dateformat') );
@ -323,6 +323,8 @@ sub get_template_and_user {
LoginBranchcode => (C4::Context->userenv?C4::Context->userenv->{"branch"}:"insecure"),
LoginFirstname => (C4::Context->userenv?C4::Context->userenv->{"firstname"}:"Bel"),
LoginSurname => C4::Context->userenv?C4::Context->userenv->{"surname"}:"Inconnu",
emailaddress => C4::Context->userenv?C4::Context->userenv->{"emailaddress"}:undef,
loggedinpersona => C4::Context->userenv?C4::Context->userenv->{"persona"}:undef,
TagsEnabled => C4::Context->preference("TagsEnabled"),
hide_marc => C4::Context->preference("hide_marc"),
item_level_itypes => C4::Context->preference('item-level_itypes'),
@ -333,8 +335,8 @@ sub get_template_and_user {
using_https => $in->{'query'}->https() ? 1 : 0,
noItemTypeImages => C4::Context->preference("noItemTypeImages"),
marcflavour => C4::Context->preference("marcflavour"),
persona => C4::Context->preference("persona"),
);
if ( $in->{'type'} eq "intranet" ) {
$template->param(
AmazonCoverImages => C4::Context->preference("AmazonCoverImages"),
@ -557,8 +559,8 @@ sub _version_check {
my $version;
# If Version syspref is unavailable, it means Koha is beeing installed,
# and so we must redirect to OPAC maintenance page or to the WebInstaller
# also, if OpacMaintenance is ON, OPAC should redirect to maintenance
if (C4::Context->preference('OpacMaintenance') && $type eq 'opac') {
# also, if OpacMaintenance is ON, OPAC should redirect to maintenance
if (C4::Context->preference('OpacMaintenance') && $type eq 'opac') {
warn "OPAC Install required, redirecting to maintenance";
print $query->redirect("/cgi-bin/koha/maintenance.pl");
safe_exit;
@ -613,11 +615,12 @@ sub _timeout_syspref {
sub checkauth {
my $query = shift;
$debug and warn "Checking Auth";
$debug and warn "Checking Auth";
# $authnotrequired will be set for scripts which will run without authentication
my $authnotrequired = shift;
my $flagsrequired = shift;
my $type = shift;
my $persona = shift;
$type = 'opac' unless $type;
my $dbh = C4::Context->dbh;
@ -634,7 +637,7 @@ sub checkauth {
# when using authentication against multiple CAS servers, as configured in Auth_cas_servers.yaml
my $casparam = $query->param('cas');
if ( $userid = $ENV{'REMOTE_USER'} ) {
if ( $userid = $ENV{'REMOTE_USER'} ) {
# Using Basic Authentication, no cookies required
$cookie = $query->cookie(
-name => 'CGISESSID',
@ -644,6 +647,9 @@ sub checkauth {
);
$loggedin = 1;
}
elsif ( $persona ){
# we dont want to set a session because we are being called by a persona callback
}
elsif ( $sessionID = $query->cookie("CGISESSID") )
{ # assignment, not comparison
my $session = get_session($sessionID);
@ -655,7 +661,8 @@ sub checkauth {
$session->param('cardnumber'), $session->param('firstname'),
$session->param('surname'), $session->param('branch'),
$session->param('branchname'), $session->param('flags'),
$session->param('emailaddress'), $session->param('branchprinter')
$session->param('emailaddress'), $session->param('branchprinter'),
$session->param('persona')
);
C4::Context::set_shelves_userenv('bar',$session->param('barshelves'));
C4::Context::set_shelves_userenv('pub',$session->param('pubshelves'));
@ -674,9 +681,9 @@ sub checkauth {
$session->flush;
$session->delete();
C4::Context->_unset_userenv($sessionID);
$sessionID = undef;
$userid = undef;
}
$sessionID = undef;
$userid = undef;
}
elsif ($logout) {
# voluntary logout the user
$session->flush;
@ -686,9 +693,9 @@ sub checkauth {
$sessionID = undef;
$userid = undef;
if ($cas and $caslogout) {
logout_cas($query);
}
if ($cas and $caslogout) {
logout_cas($query);
}
}
elsif ( $lasttime < time() - $timeout ) {
# timed logout
@ -728,6 +735,7 @@ sub checkauth {
}
}
unless ($userid || $sessionID) {
#we initiate a session prior to checking for a username to allow for anonymous sessions...
my $session = get_session("") or die "Auth ERROR: Cannot get_session()";
my $sessionID = $session->id;
@ -741,9 +749,10 @@ sub checkauth {
if ( ( $cas && $query->param('ticket') )
|| $userid
|| ( my $pki_field = C4::Context->preference('AllowPKIAuth') ) ne
'None' )
'None' || $persona )
{
my $password = $query->param('password');
my ( $return, $cardnumber );
if ( $cas && $query->param('ticket') ) {
my $retuserid;
@ -752,7 +761,29 @@ sub checkauth {
$userid = $retuserid;
$info{'invalidCasLogin'} = 1 unless ($return);
}
elsif (
elsif ($persona) {
my $value = $persona;
# If we're looking up the email, there's a chance that the person
# doesn't have a userid. So if there is none, we pass along the
# borrower number, and the bits of code that need to know the user
# ID will have to be smart enough to handle that.
require C4::Members;
my @users_info = C4::Members::GetBorrowersWithEmail($value);
if (@users_info) {
# First the userid, then the borrowernum
$value = $users_info[0][1] || $users_info[0][0];
}
else {
undef $value;
}
$return = $value ? 1 : 0;
$userid = $value;
}
elsif (
( $pki_field eq 'Common Name' && $ENV{'SSL_CLIENT_S_DN_CN'} )
|| ( $pki_field eq 'emailAddress'
&& $ENV{'SSL_CLIENT_S_DN_Email'} )
@ -780,25 +811,26 @@ sub checkauth {
}
}
# 0 for no user, 1 for normal, 2 for demo user.
$return = $value ? 1 : 0;
$userid = $value;
}
}
else {
my $retuserid;
( $return, $cardnumber, $retuserid ) =
checkpw( $dbh, $userid, $password, $query );
$userid = $retuserid if ( $retuserid ne '' );
}
if ($return) {
}
if ($return) {
#_session_log(sprintf "%20s from %16s logged in at %30s.\n", $userid,$ENV{'REMOTE_ADDR'},(strftime '%c', localtime));
if ( $flags = haspermission( $userid, $flagsrequired ) ) {
$loggedin = 1;
}
else {
$info{'nopermission'} = 1;
C4::Context->_unset_userenv($sessionID);
}
if ( $flags = haspermission( $userid, $flagsrequired ) ) {
$loggedin = 1;
}
else {
$info{'nopermission'} = 1;
C4::Context->_unset_userenv($sessionID);
}
my ($borrowernumber, $firstname, $surname, $userflags,
$branchcode, $branchname, $branchprinter, $emailaddress);
@ -894,33 +926,37 @@ sub checkauth {
$session->param('ip',$session->remote_addr());
$session->param('lasttime',time());
}
if ($persona){
$session->param('persona',1);
}
C4::Context::set_userenv(
$session->param('number'), $session->param('id'),
$session->param('cardnumber'), $session->param('firstname'),
$session->param('surname'), $session->param('branch'),
$session->param('branchname'), $session->param('flags'),
$session->param('emailaddress'), $session->param('branchprinter')
$session->param('emailaddress'), $session->param('branchprinter'),
$session->param('persona')
);
}
else {
if ($userid) {
$info{'invalid_username_or_password'} = 1;
C4::Context->_unset_userenv($sessionID);
}
}
} # END if ( $userid = $query->param('userid') )
elsif ($type eq "opac") {
else {
if ($userid) {
$info{'invalid_username_or_password'} = 1;
C4::Context->_unset_userenv($sessionID);
}
}
} # END if ( $userid = $query->param('userid') )
elsif ($type eq "opac") {
# if we are here this is an anonymous session; add public lists to it and a few other items...
# anonymous sessions are created only for the OPAC
$debug and warn "Initiating an anonymous session...";
$debug and warn "Initiating an anonymous session...";
# setting a couple of other session vars...
$session->param('ip',$session->remote_addr());
$session->param('lasttime',time());
$session->param('sessiontype','anon');
}
} # END unless ($userid)
# setting a couple of other session vars...
$session->param('ip',$session->remote_addr());
$session->param('lasttime',time());
$session->param('sessiontype','anon');
}
} # END unless ($userid)
my $insecure = C4::Context->boolean_preference('insecure');
# finished authentification, now respond
@ -992,6 +1028,7 @@ sub checkauth {
wrongip => $info{'wrongip'},
PatronSelfRegistration => C4::Context->preference("PatronSelfRegistration"),
PatronSelfRegistrationDefaultCategory => C4::Context->preference("PatronSelfRegistrationDefaultCategory"),
persona => C4::Context->preference("Persona"),
);
$template->param( OpacPublic => C4::Context->preference("OpacPublic"));
@ -999,24 +1036,23 @@ sub checkauth {
if ($cas) {
# Is authentication against multiple CAS servers enabled?
# Is authentication against multiple CAS servers enabled?
if (C4::Auth_with_cas::multipleAuth && !$casparam) {
my $casservers = C4::Auth_with_cas::getMultipleAuth();
my @tmplservers;
foreach my $key (keys %$casservers) {
push @tmplservers, {name => $key, value => login_cas_url($query, $key) . "?cas=$key" };
}
#warn Data::Dumper::Dumper(\@tmplservers);
$template->param(
casServersLoop => \@tmplservers
);
} else {
my $casservers = C4::Auth_with_cas::getMultipleAuth();
my @tmplservers;
foreach my $key (keys %$casservers) {
push @tmplservers, {name => $key, value => login_cas_url($query, $key) . "?cas=$key" };
}
$template->param(
casServersLoop => \@tmplservers
);
} else {
$template->param(
casServerUrl => login_cas_url($query),
);
}
);
}
$template->param(
$template->param(
invalidCasLogin => $info{'invalidCasLogin'}
);
}
@ -1161,23 +1197,23 @@ sub check_api_auth {
# new login
my $userid = $query->param('userid');
my $password = $query->param('password');
my ($return, $cardnumber);
my ($return, $cardnumber);
# Proxy CAS auth
if ($cas && $query->param('PT')) {
my $retuserid;
$debug and print STDERR "## check_api_auth - checking CAS\n";
# In case of a CAS authentication, we use the ticket instead of the password
my $PT = $query->param('PT');
($return,$cardnumber,$userid) = check_api_auth_cas($dbh, $PT, $query); # EXTERNAL AUTH
} else {
# User / password auth
unless ($userid and $password) {
# caller did something wrong, fail the authenticateion
return ("failed", undef, undef);
}
( $return, $cardnumber ) = checkpw( $dbh, $userid, $password, $query );
}
# Proxy CAS auth
if ($cas && $query->param('PT')) {
my $retuserid;
$debug and print STDERR "## check_api_auth - checking CAS\n";
# In case of a CAS authentication, we use the ticket instead of the password
my $PT = $query->param('PT');
($return,$cardnumber,$userid) = check_api_auth_cas($dbh, $PT, $query); # EXTERNAL AUTH
} else {
# User / password auth
unless ($userid and $password) {
# caller did something wrong, fail the authenticateion
return ("failed", undef, undef);
}
( $return, $cardnumber ) = checkpw( $dbh, $userid, $password, $query );
}
if ($return and haspermission( $userid, $flagsrequired)) {
my $session = get_session("");
@ -1420,7 +1456,7 @@ sub get_session {
$session = new CGI::Session("driver:PostgreSQL;serializer:yaml;id:md5", $sessionID, {Handle=>$dbh});
}
elsif ($storage_method eq 'memcached' && C4::Context->ismemcached){
$session = new CGI::Session("driver:memcached;serializer:yaml;id:md5", $sessionID, { Memcached => C4::Context->memcached } );
$session = new CGI::Session("driver:memcached;serializer:yaml;id:md5", $sessionID, { Memcached => C4::Context->memcached } );
}
else {
# catch all defaults to tmp should work on all systems
@ -1440,11 +1476,11 @@ sub checkpw {
if ($cas && $query && $query->param('ticket')) {
$debug and print STDERR "## checkpw - checking CAS\n";
# In case of a CAS authentication, we use the ticket instead of the password
my $ticket = $query->param('ticket');
# In case of a CAS authentication, we use the ticket instead of the password
my $ticket = $query->param('ticket');
my ($retval,$retcard,$retuserid) = checkpw_cas($dbh, $ticket, $query); # EXTERNAL AUTH
($retval) and return ($retval,$retcard,$retuserid);
return 0;
return 0;
}
# INTERNAL AUTH

View File

@ -1057,7 +1057,8 @@ sub userenv {
=head2 set_userenv
C4::Context->set_userenv($usernum, $userid, $usercnum, $userfirstname,
$usersurname, $userbranch, $userflags, $emailaddress);
$usersurname, $userbranch, $userflags, $emailaddress, $branchprinter,
$persona);
Establish a hash of user environment variables.
@ -1067,7 +1068,7 @@ set_userenv is called in Auth.pm
#'
sub set_userenv {
my ($usernum, $userid, $usercnum, $userfirstname, $usersurname, $userbranch, $branchname, $userflags, $emailaddress, $branchprinter)= @_;
my ($usernum, $userid, $usercnum, $userfirstname, $usersurname, $userbranch, $branchname, $userflags, $emailaddress, $branchprinter, $persona)= @_;
my $var=$context->{"activeuser"} || '';
my $cell = {
"number" => $usernum,
@ -1080,7 +1081,8 @@ sub set_userenv {
"branchname" => $branchname,
"flags" => $userflags,
"emailaddress" => $emailaddress,
"branchprinter" => $branchprinter
"branchprinter" => $branchprinter,
"persona" => $persona,
};
$context->{userenv}->{$var} = $cell;
return $cell;

View File

@ -415,3 +415,4 @@ INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) V
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('OPACNumbersPreferPhrase','0', NULL, 'Control the use of phr operator in callnumber and standard number OPAC searches', 'YesNo');
INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ('IntranetNumbersPreferPhrase','0', NULL, 'Control the use of phr operator in callnumber and standard number staff client searches', 'YesNo');
INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('UNIMARCField100Language', 'fre','UNIMARC field 100 default language',NULL,'short');
INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('Persona',0,'Use Mozilla Persona for login','','YesNo');

View File

@ -6428,6 +6428,15 @@ if ( CheckVersion($DBversion) ) {
SetVersion($DBversion);
}
$DBversion = "3.11.00.022";
if ( CheckVersion($DBversion) ) {
$dbh->do(
"INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('Persona',0,'Use Mozilla Persona for login','','YesNo')"
);
print "Upgrade to $DBversion done (Bug 9587 - Allow login via Persona)\n";
SetVersion($DBversion);
}
=head1 FUNCTIONS

View File

@ -104,6 +104,14 @@ Administration:
Common Name: the Common Name
emailAddress: the emailAddress
- field for SSL client certificate authentication
Mozilla Persona:
-
- pref: Persona
default: 0
choices:
yes: Allow
no: "Don't Allow"
- Mozilla persona for login
Search Engine:
-
- pref: SearchEngine

View File

@ -0,0 +1,228 @@
/* Link body */
.persona-button{
color: #fff;
display: inline-block;
font-size: 14px;
font-family: Helvetica, Arial, sans-serif;
font-weight: bold;
line-height: 1.1;
overflow: hidden;
position: relative;
text-decoration: none;
text-shadow: 0 1px rgba(0,0,0,0.5), 0 0 2px rgba(0,0,0,0.2);
background: #297dc3;
background: -moz-linear-gradient(top, #43a6e2, #287cc2);
background: -ms-linear-gradient(top, #43a6e2, #287cc2);
background: -o-linear-gradient(top, #43a6e2, #287cc2);
background: -webkit-linear-gradient(top, #43a6e2, #287cc2);
background: linear-gradient(top, #43a6e2, #287cc2);
-moz-border-radius: 3px;
-ms-border-radius: 3px;
-o-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
-moz-box-shadow: 0 1px 0 rgba(0,0,0,0.2);
-ms-box-shadow: 0 1px 0 rgba(0,0,0,0.2);
-o-box-shadow: 0 1px 0 rgba(0,0,0,0.2);
-webkit-box-shadow: 0 1px 0 rgba(0,0,0,0.2);
box-shadow: 0 1px 0 rgba(0,0,0,0.2);
}
.persona-button:hover{
background: #21669f;
background: -moz-linear-gradient(top, #3788b9, #21669f);
background: -ms-linear-gradient(top, #3788b9, #21669f);
background: -o-linear-gradient(top, #3788b9, #21669f);
background: -webkit-linear-gradient(top, #3788b9, #21669f);
background: linear-gradient(top, #3788b9, #21669f);
}
.persona-button:active, .persona-button:focus{
top: 1px;
-moz-box-shadow: none;
-ms-box-shadow: none;
-o-box-shadow: none;
-webkit-box-shadow: none;
box-shadow: none;
}
.persona-button span{
display: inline-block;
padding: 5px 10px 5px 40px;
}
/* Icon */
.persona-button span:after{
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAAPCAYAAAA/I0V3AAAA4klEQVR42o2RWaqEMBRE3YaCiDjPwQGcd9CrysLv4wTyoLFD90dxqbp1EgdPRB7Kskznea6Zn/aPoKoqUUrJOI5m4l2QBfSyLHKep1zXZSae3An1fS/7vst931bGkzuhaZrsLVbGkzuheZ7lOI6HyJ2QUkqv6yrbtv0LT+6E7G0UrfBfP3lZlpoXH4ZBmHgn5Pv+KwxDfqp0XQdgJp6c/RsUBIGOokiSJDE/s21bACbe5Ozp0TdAHMdSFIXUdS1N01C2wpObPT36HifwCJzI0iX29Oh7XP0E3CB9L01TzM+i/wePv4ZE5RtAngAAAABJRU5ErkJggg==) 10px center no-repeat;
content: '';
display: block;
width: 31px;
position: absolute;
bottom: 0;
left: -3px;
top: 0;
z-index: 10;
}
/* Icon background */
.persona-button span:before{
content: '';
display: block;
height: 100%;
width: 20px;
position: absolute;
bottom: 0;
left: 0;
top: 0;
z-index: 1;
background: #42a9dd;
background: -moz-linear-gradient(top, #50b8e8, #3095ce);
background: -ms-linear-gradient(top, #50b8e8, #3095ce);
background: -o-linear-gradient(top, #50b8e8, #3095ce);
background: -webkit-linear-gradient(top, #50b8e8, #3095ce);
background: linear-gradient(top, #50b8e8, #3095ce);
-moz-border-radius: 3px 0 0 3px;
-ms-border-radius: 3px 0 0 3px;
-o-border-radius: 3px 0 0 3px;
-webkit-border-radius: 3px 0 0 3px;
border-radius: 3px 0 0 3px;
}
/* Triangle */
.persona-button:before{
background: #42a9dd;
content: '';
display: block;
height: 26px;
width: 26px;
position: absolute;
left: 2px;
top: 50%;
margin-top: -13px;
z-index: 0;
background: -moz-linear-gradient(-45deg, #50b8e8, #3095ce);
background: -ms-linear-gradient(-45deg, #50b8e8, #3095ce);
background: -o-linear-gradient(-45deg, #50b8e8, #3095ce);
background: -webkit-linear-gradient(-45deg, #50b8e8, #3095ce);
background: linear-gradient(-45deg, #3095ce, #50b8e8); /* flipped for updated spec */
-moz-box-shadow: 1px -1px 1px rgba(0,0,0,0.1);
-ms-box-shadow: 1px -1px 1px rgba(0,0,0,0.1);
-o-box-shadow: 1px -1px 1px rgba(0,0,0,0.1);
-webkit-box-shadow: 1px -1px 1px rgba(0,0,0,0.1);
box-shadow: 1px -1px 1px rgba(0,0,0,0.1);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
}
/* Inset shadow (required here because the icon background clips it when on the `a` element) */
.persona-button:after{
content: '';
display: block;
height: 100%;
width: 100%;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: 10;
-moz-border-radius: 3px;
-ms-border-radius: 3px;
-o-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
-moz-box-shadow: inset 0 -1px 0 rgba(0,0,0,0.3);
-ms-box-shadow: inset 0 -1px 0 rgba(0,0,0,0.3);
-o-box-shadow: inset 0 -1px 0 rgba(0,0,0,0.3);
-webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,0.3);
box-shadow: inset 0 -1px 0 rgba(0,0,0,0.3);
}
/* ========================================================
* Dark button
* ===================================================== */
.persona-button.dark{
background: #3c3c3c;
background: -moz-linear-gradient(top, #606060, #3c3c3c);
background: -ms-linear-gradient(top, #606060, #3c3c3c);
background: -o-linear-gradient(top, #606060, #3c3c3c);
background: -webkit-linear-gradient(top, #606060, #3c3c3c);
background: linear-gradient(top, #606060, #3c3c3c);
}
.persona-button.dark:hover{
background: #2d2d2d;
background: -moz-linear-gradient(top, #484848, #2d2d2d);
background: -ms-linear-gradient(top, #484848, #2d2d2d);
background: -o-linear-gradient(top, #484848, #2d2d2d);
background: -webkit-linear-gradient(top, #484848, #2d2d2d);
background: linear-gradient(top, #484848, #2d2d2d);
}
.persona-button.dark span:before{ /* Icon BG */
background: #d34f2d;
background: -moz-linear-gradient(top, #ebac45, #d34f2d);
background: -ms-linear-gradient(top, #ebac45, #d34f2d);
background: -o-linear-gradient(top, #ebac45, #d34f2d);
background: -webkit-linear-gradient(top, #ebac45, #d34f2d);
background: linear-gradient(top, #ebac45, #d34f2d);
}
.persona-button.dark:before{ /* Triangle */
background: #d34f2d;
background: -moz-linear-gradient(-45deg, #ebac45, #d34f2d);
background: -ms-linear-gradient(-45deg, #ebac45, #d34f2d);
background: -o-linear-gradient(-45deg, #ebac45, #d34f2d);
background: -webkit-linear-gradient(-45deg, #ebac45, #d34f2d);
background: linear-gradient(-45deg, #d34f2d, #ebac45); /* flipped for updated spec */
}
/* ========================================================
* Orange button
* ===================================================== */
.persona-button.orange{
background: #ee731a;
background: -moz-linear-gradient(top, #ee731a, #d03116);
background: -ms-linear-gradient(top, #ee731a, #d03116);
background: -o-linear-gradient(top, #ee731a, #d03116);
background: -webkit-linear-gradient(top, #ee731a, #d03116);
background: linear-gradient(top, #ee731a, #d03116);
}
.persona-button.orange:hover{
background: #cb6216;
background: -moz-linear-gradient(top, #cb6216, #b12a13);
background: -ms-linear-gradient(top, #cb6216, #b12a13);
background: -o-linear-gradient(top, #cb6216, #b12a13);
background: -webkit-linear-gradient(top, #cb6216, #b12a13);
background: linear-gradient(top, #cb6216, #b12a13);
}
.persona-button.orange span:before{ /* Icon BG */
background: #e84a21;
background: -moz-linear-gradient(top, #f7ad27, #e84a21);
background: -ms-linear-gradient(top, #f7ad27, #e84a21);
background: -o-linear-gradient(top, #f7ad27, #e84a21);
background: -webkit-linear-gradient(top, #f7ad27, #e84a21);
background: linear-gradient(top, #f7ad27, #e84a21);
}
.persona-button.orange:before{ /* Triangle */
background: #e84a21;
background: -moz-linear-gradient(-45deg, #f7ad27, #e84a21);
background: -ms-linear-gradient(-45deg, #f7ad27, #e84a21);
background: -o-linear-gradient(-45deg, #f7ad27, #e84a21);
background: -webkit-linear-gradient(-45deg, #f7ad27, #e84a21);
background: linear-gradient(-45deg, #e84a21, #f7ad27); /* flipped for updated spec */
}

View File

@ -20,6 +20,9 @@
<link rel="stylesheet" type="text/css" href="[% themelang %]/css/[% opac_css_override %]" />
[% END %]
<link rel="stylesheet" type="text/css" media="print" href="[% themelang %]/css/print.css" />
[% IF persona %]
<link rel="stylesheet" type="text/css" href="[% themelang %]/css/persona-buttons.css" />
[% END %]
[% IF ( OPACMobileUserCSS ) %]<style type="text/css" media="screen and (max-width:700px)">[% OPACMobileUserCSS %]</style>[% END %]
[% IF ( OPACUserCSS ) %]<style type="text/css">[% OPACUserCSS %]</style>[% END %]
<!-- yui js -->

View File

@ -10,7 +10,7 @@
[% IF ( ShowOpacRecentSearchLink ) %]
<li><a href="/cgi-bin/koha/opac-search-history.pl" title="View your search history">Search history</a> [<a class="logout" href="/cgi-bin/koha/opac-search-history.pl?action=delete" title="Delete your search history" onclick="return confirm(MSG_DELETE_SEARCH_HISTORY);">x</a>]</li>
[% END %]
[% IF ( loggedinusername ) %]<li><a class="logout" id="logout" href="/cgi-bin/koha/opac-main.pl?logout.x=1">Log Out</a></li>[% END %]
[% IF ( loggedinusername ) %]<li>[% IF persona %]<a class="logout" id="logout" href="/cgi-bin/koha/opac-main.pl?logout.x=1" onclick='navigator.id.logout();'>[% ELSE %]<a class="logout" id="logout" href="/cgi-bin/koha/opac-main.pl?logout.x=1">[% END %]Log Out</a></li>[% END %]
</ul>
[% END %]
</div>

View File

@ -60,5 +60,44 @@
[% END %]
[% IF persona %]
<script src="https://login.persona.org/include.js"></script>
<script type="text/javascript" language="javascript">
navigator.id.watch({
loggedInUser: [% IF emailaddress && loggedinpersona %]'[% emailaddress %]'[% ELSE %]null[% END %],
onlogin: function (assertion) {
$.post('/cgi-bin/koha/svc/login',
{ assertion: assertion },
function (data) {
window.location = '/cgi-bin/koha/opac-user.pl';
}
)
.fail(function() { var errstr = _("Could not login, perhaps your Persona email does not match your Koha one");
alert(errstr);
});
},
onlogout: function () {
window.location = '/cgi-bin/koha/opac-main.pl?logout.x=1';
}
});
var signinLink = document.getElementById('browserid');
if (signinLink) {
signinLink.onclick = function(evt) {
// Requests a signed identity assertion from the user.
navigator.id.request({
siteName: "[% LibraryName | html %]",
returnTo: '/cgi-bin/koha/opac-user.pl',
oncancel: function() { alert('user refuses to share identity.'); }
});
};
}
</script>
[% END %]
</body>
</html>

File diff suppressed because one or more lines are too long

View File

@ -99,7 +99,13 @@ please choose against which one you would like to authenticate: </p>
<a href="mailto:[% admin %]">email the Koha Administrator</a>.</li>
<li>Use top menu bar to navigate to another part of Koha.</li>
</ul>
[% END %]</div>
[% END %]
[% IF persona %]
<a href="#" class="persona-button" id="browserid" ><span>Sign in with your Email</span></a>
[% END %]
</div>
</div>
</div>
</div>

View File

@ -63,6 +63,9 @@
</form>
</div>
[% END %]
[% IF persona %]
<a href="#" class="persona-button" id="browserid" ><span>Sign in with your Email</span></a>
[% END %]
[% END %]
[% END %]
[% IF ( OpacNavRight ) %]<div id="opacrightsidebar" class="container">[% OpacNavRight %]</div>[% END %]

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -16,7 +16,7 @@ the kohaversion is divided in 4 parts :
use strict;
sub kohaversion {
our $VERSION = '3.11.00.021';
our $VERSION = '3.11.00.022';
# version needs to be set this way
# so that it can be picked up by Makefile.PL
# during install

58
opac/svc/login Executable file
View File

@ -0,0 +1,58 @@
#!/usr/bin/perl
# Copyright chris@bigballofwax.co.nz 2013
#
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation; either version 3 of the License, or (at your option) any later
# version.
#
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with Koha; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
use CGI;
use strict;
use warnings;
use C4::Auth;
use C4::Context;
use LWP::UserAgent;
use HTTP::Request::Common qw{ POST };
use JSON qw( decode_json );
my $url = 'https://verifier.login.persona.org/verify';
my $query = CGI->new();
my $host = C4::Context->preference('OPACBaseURL');
my $assertion = $query->param('assertion');
my $ua = LWP::UserAgent->new();
my $response =
$ua->post( $url, [ 'assertion' => $assertion, 'audience' => $host ] );
if ( $response->is_success ) {
my $content = $response->decoded_content();
my $decoded_json = decode_json($content);
my ( $userid, $cookie, $sessionID ) =
checkauth( $query, 1, { borrow => 1 }, 'opac', $decoded_json->{'email'} );
if ($userid) { # a valid user has logged in
print $query->header( -cookie => $cookie );
print $decoded_json;
}
else {
# logged in with an email that isn't associated with a borrower
die "Email not associated with a borrower";
}
}
else {
warn $response->status_line, "\n";
}