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

(-)a/C4/Auth.pm (-9 / +42 lines)
Lines 323-328 sub get_template_and_user { Link Here
323
            LoginBranchcode              => (C4::Context->userenv?C4::Context->userenv->{"branch"}:"insecure"),
323
            LoginBranchcode              => (C4::Context->userenv?C4::Context->userenv->{"branch"}:"insecure"),
324
            LoginFirstname               => (C4::Context->userenv?C4::Context->userenv->{"firstname"}:"Bel"),
324
            LoginFirstname               => (C4::Context->userenv?C4::Context->userenv->{"firstname"}:"Bel"),
325
            LoginSurname                 => C4::Context->userenv?C4::Context->userenv->{"surname"}:"Inconnu",
325
            LoginSurname                 => C4::Context->userenv?C4::Context->userenv->{"surname"}:"Inconnu",
326
            emailaddress                 => C4::Context->userenv?C4::Context->userenv->{"emailaddress"}:undef,
326
            TagsEnabled                  => C4::Context->preference("TagsEnabled"),
327
            TagsEnabled                  => C4::Context->preference("TagsEnabled"),
327
            hide_marc                    => C4::Context->preference("hide_marc"),
328
            hide_marc                    => C4::Context->preference("hide_marc"),
328
            item_level_itypes            => C4::Context->preference('item-level_itypes'),
329
            item_level_itypes            => C4::Context->preference('item-level_itypes'),
Lines 333-338 sub get_template_and_user { Link Here
333
            using_https                  => $in->{'query'}->https() ? 1 : 0,
334
            using_https                  => $in->{'query'}->https() ? 1 : 0,
334
            noItemTypeImages             => C4::Context->preference("noItemTypeImages"),
335
            noItemTypeImages             => C4::Context->preference("noItemTypeImages"),
335
            marcflavour                  => C4::Context->preference("marcflavour"),
336
            marcflavour                  => C4::Context->preference("marcflavour"),
337
            persona                      => C4::Context->preference("persona"),
336
    );
338
    );
337
339
338
    if ( $in->{'type'} eq "intranet" ) {
340
    if ( $in->{'type'} eq "intranet" ) {
Lines 618-623 sub checkauth { Link Here
618
    my $authnotrequired = shift;
620
    my $authnotrequired = shift;
619
    my $flagsrequired   = shift;
621
    my $flagsrequired   = shift;
620
    my $type            = shift;
622
    my $type            = shift;
623
    my $persona         = shift;
621
    $type = 'opac' unless $type;
624
    $type = 'opac' unless $type;
622
625
623
    my $dbh     = C4::Context->dbh;
626
    my $dbh     = C4::Context->dbh;
Lines 634-640 sub checkauth { Link Here
634
    # when using authentication against multiple CAS servers, as configured in Auth_cas_servers.yaml
637
    # when using authentication against multiple CAS servers, as configured in Auth_cas_servers.yaml
635
    my $casparam = $query->param('cas');
638
    my $casparam = $query->param('cas');
636
639
637
        if ( $userid = $ENV{'REMOTE_USER'} ) {
640
    if ( $userid = $ENV{'REMOTE_USER'} ) {
638
            # Using Basic Authentication, no cookies required
641
            # Using Basic Authentication, no cookies required
639
        $cookie = $query->cookie(
642
        $cookie = $query->cookie(
640
            -name     => 'CGISESSID',
643
            -name     => 'CGISESSID',
Lines 644-649 sub checkauth { Link Here
644
        );
647
        );
645
        $loggedin = 1;
648
        $loggedin = 1;
646
    }
649
    }
650
    elsif ( $persona ){
651
      # we dont want to set a session because we are being called by a persona callback
652
    }
647
    elsif ( $sessionID = $query->cookie("CGISESSID") )
653
    elsif ( $sessionID = $query->cookie("CGISESSID") )
648
    {    # assignment, not comparison
654
    {    # assignment, not comparison
649
        my $session = get_session($sessionID);
655
        my $session = get_session($sessionID);
Lines 728-733 sub checkauth { Link Here
728
        }
734
        }
729
    }
735
    }
730
    unless ($userid || $sessionID) {
736
    unless ($userid || $sessionID) {
737
	
731
        #we initiate a session prior to checking for a username to allow for anonymous sessions...
738
        #we initiate a session prior to checking for a username to allow for anonymous sessions...
732
        my $session = get_session("") or die "Auth ERROR: Cannot get_session()";
739
        my $session = get_session("") or die "Auth ERROR: Cannot get_session()";
733
        my $sessionID = $session->id;
740
        my $sessionID = $session->id;
Lines 737-749 sub checkauth { Link Here
737
            -value    => $session->id,
744
            -value    => $session->id,
738
            -HttpOnly => 1
745
            -HttpOnly => 1
739
        );
746
        );
740
    $userid = $query->param('userid');
747
	$userid = $query->param('userid');
741
        if (   ( $cas && $query->param('ticket') )
748
        if (   ( $cas && $query->param('ticket') )
742
            || $userid
749
            || $userid
743
            || ( my $pki_field = C4::Context->preference('AllowPKIAuth') ) ne
750
            || ( my $pki_field = C4::Context->preference('AllowPKIAuth') ) ne
744
            'None' )
751
            'None' || $persona )
745
        {
752
        {
746
            my $password = $query->param('password');
753
            my $password = $query->param('password');
754
		
747
            my ( $return, $cardnumber );
755
            my ( $return, $cardnumber );
748
            if ( $cas && $query->param('ticket') ) {
756
            if ( $cas && $query->param('ticket') ) {
749
                my $retuserid;
757
                my $retuserid;
Lines 752-758 sub checkauth { Link Here
752
                $userid = $retuserid;
760
                $userid = $retuserid;
753
                $info{'invalidCasLogin'} = 1 unless ($return);
761
                $info{'invalidCasLogin'} = 1 unless ($return);
754
            }
762
            }
755
            elsif (
763
	    
764
    elsif ($persona) {
765
        my $value = $persona;
766
767
        # If we're looking up the email, there's a chance that the person
768
        # doesn't have a userid. So if there is none, we pass along the
769
        # borrower number, and the bits of code that need to know the user
770
        # ID will have to be smart enough to handle that.
771
        require C4::Members;
772
        my @users_info = C4::Members::GetBorrowersWithEmail($value);
773
        if (@users_info) {
774
775
            # First the userid, then the borrowernum
776
            $value = $users_info[0][1] || $users_info[0][0];
777
        }
778
        else {
779
            undef $value;
780
        }
781
        $return = $value ? 1 : 0;
782
        $userid = $value;
783
784
    }
785
786
    elsif (
756
                ( $pki_field eq 'Common Name' && $ENV{'SSL_CLIENT_S_DN_CN'} )
787
                ( $pki_field eq 'Common Name' && $ENV{'SSL_CLIENT_S_DN_CN'} )
757
                || (   $pki_field eq 'emailAddress'
788
                || (   $pki_field eq 'emailAddress'
758
                    && $ENV{'SSL_CLIENT_S_DN_Email'} )
789
                    && $ENV{'SSL_CLIENT_S_DN_Email'} )
Lines 779-796 sub checkauth { Link Here
779
                        undef $value;
810
                        undef $value;
780
                    }
811
                    }
781
                }
812
                }
782
813
		
783
                # 0 for no user, 1 for normal, 2 for demo user.
814
        
784
                $return = $value ? 1 : 0;
815
                $return = $value ? 1 : 0;
785
                $userid = $value;
816
                $userid = $value;
786
            }
817
		
818
	}
787
            else {
819
            else {
788
                my $retuserid;
820
                my $retuserid;
789
                ( $return, $cardnumber, $retuserid ) =
821
                ( $return, $cardnumber, $retuserid ) =
790
                  checkpw( $dbh, $userid, $password, $query );
822
                  checkpw( $dbh, $userid, $password, $query );
791
                $userid = $retuserid if ( $retuserid ne '' );
823
                $userid = $retuserid if ( $retuserid ne '' );
792
            }
824
        }
793
		if ($return) {
825
	    if ($return) {
794
               #_session_log(sprintf "%20s from %16s logged in  at %30s.\n", $userid,$ENV{'REMOTE_ADDR'},(strftime '%c', localtime));
826
               #_session_log(sprintf "%20s from %16s logged in  at %30s.\n", $userid,$ENV{'REMOTE_ADDR'},(strftime '%c', localtime));
795
            	if ( $flags = haspermission(  $userid, $flagsrequired ) ) {
827
            	if ( $flags = haspermission(  $userid, $flagsrequired ) ) {
796
					$loggedin = 1;
828
					$loggedin = 1;
Lines 992-997 sub checkauth { Link Here
992
        wrongip            => $info{'wrongip'},
1024
        wrongip            => $info{'wrongip'},
993
        PatronSelfRegistration => C4::Context->preference("PatronSelfRegistration"),
1025
        PatronSelfRegistration => C4::Context->preference("PatronSelfRegistration"),
994
        PatronSelfRegistrationDefaultCategory => C4::Context->preference("PatronSelfRegistrationDefaultCategory"),
1026
        PatronSelfRegistrationDefaultCategory => C4::Context->preference("PatronSelfRegistrationDefaultCategory"),
1027
        persona            => C4::Context->preference("Persona"),
995
    );
1028
    );
996
1029
997
    $template->param( OpacPublic => C4::Context->preference("OpacPublic"));
1030
    $template->param( OpacPublic => C4::Context->preference("OpacPublic"));
(-)a/installer/data/mysql/sysprefs.sql (+1 lines)
Lines 411-413 INSERT INTO systempreferences (variable,value,options,explanation,type) VALUES ( Link Here
411
INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('IDreamBooksReviews','0','Display book review snippets from IDreamBooks.com','','YesNo');
411
INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('IDreamBooksReviews','0','Display book review snippets from IDreamBooks.com','','YesNo');
412
INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('IDreamBooksReadometer','0','Display Readometer from IDreamBooks.com','','YesNo');
412
INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('IDreamBooksReadometer','0','Display Readometer from IDreamBooks.com','','YesNo');
413
INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('IDreamBooksResults','0','Display IDreamBooks.com rating in search results','','YesNo');
413
INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('IDreamBooksResults','0','Display IDreamBooks.com rating in search results','','YesNo');
414
INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('Persona',0,'Use Mozilla Persona for login','','YesNo');
(-)a/installer/data/mysql/updatedatabase.pl (+9 lines)
Lines 6399-6404 if ( CheckVersion($DBversion) ) { Link Here
6399
    SetVersion($DBversion);
6399
    SetVersion($DBversion);
6400
}
6400
}
6401
6401
6402
$DBversion = "XXX";
6403
if ( CheckVersion($DBversion) ) {
6404
    $dbh->do(
6405
"INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES('Persona',0,'Use Mozilla Persona for login','','YesNo')"
6406
    );
6407
    print "Upgrade to $DBversion done (Bug 9587 Allow login via Persona)\n";
6408
    SetVersion($DBversion);
6409
}
6410
6402
6411
6403
=head1 FUNCTIONS
6412
=head1 FUNCTIONS
6404
6413
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/admin.pref (+8 lines)
Lines 104-109 Administration: Link Here
104
                  Common Name: the Common Name
104
                  Common Name: the Common Name
105
                  emailAddress: the emailAddress
105
                  emailAddress: the emailAddress
106
            - field for SSL client certificate authentication
106
            - field for SSL client certificate authentication
107
    Mozilla Persona:
108
        -
109
            - pref: Persona
110
              default: 0
111
              choices:
112
                  yes: Allow
113
                  no: "Don't Allow"
114
            - Mozilla persona for login
107
    Search Engine:
115
    Search Engine:
108
        -
116
        -
109
            - pref: SearchEngine
117
            - pref: SearchEngine
(-)a/koha-tmpl/opac-tmpl/prog/en/css/persona-buttons.css (+228 lines)
Line 0 Link Here
1
/* Link body */
2
.persona-button{
3
  color: #fff;
4
  display: inline-block;
5
  font-size: 14px;
6
  font-family: Helvetica, Arial, sans-serif;
7
  font-weight: bold;
8
  line-height: 1.1;
9
  overflow: hidden;
10
  position: relative;
11
  text-decoration: none;
12
  text-shadow: 0 1px rgba(0,0,0,0.5), 0 0 2px rgba(0,0,0,0.2);
13
14
  background: #297dc3;
15
  background: -moz-linear-gradient(top, #43a6e2, #287cc2);
16
  background: -ms-linear-gradient(top, #43a6e2, #287cc2);
17
  background: -o-linear-gradient(top, #43a6e2, #287cc2);
18
  background: -webkit-linear-gradient(top, #43a6e2, #287cc2);
19
  background: linear-gradient(top, #43a6e2, #287cc2);
20
21
  -moz-border-radius:   3px;
22
  -ms-border-radius:     3px;
23
  -o-border-radius:     3px;
24
  -webkit-border-radius:   3px;
25
  border-radius:       3px;
26
27
  -moz-box-shadow:   0 1px 0 rgba(0,0,0,0.2);
28
  -ms-box-shadow:   0 1px 0 rgba(0,0,0,0.2);
29
  -o-box-shadow:     0 1px 0 rgba(0,0,0,0.2);
30
  -webkit-box-shadow: 0 1px 0 rgba(0,0,0,0.2);
31
  box-shadow:     0 1px 0 rgba(0,0,0,0.2);
32
}
33
34
.persona-button:hover{
35
  background: #21669f;
36
  background: -moz-linear-gradient(top, #3788b9, #21669f);
37
  background: -ms-linear-gradient(top, #3788b9, #21669f);
38
  background: -o-linear-gradient(top, #3788b9, #21669f);
39
  background: -webkit-linear-gradient(top, #3788b9, #21669f);
40
  background: linear-gradient(top, #3788b9, #21669f);
41
}
42
43
.persona-button:active, .persona-button:focus{
44
  top: 1px;
45
  -moz-box-shadow:   none;
46
  -ms-box-shadow:   none;
47
  -o-box-shadow:     none;
48
  -webkit-box-shadow: none;
49
  box-shadow:     none;
50
}
51
52
.persona-button span{
53
  display: inline-block;
54
  padding: 5px 10px 5px 40px;
55
}
56
57
/* Icon */
58
.persona-button span:after{
59
  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAAPCAYAAAA/I0V3AAAA4klEQVR42o2RWaqEMBRE3YaCiDjPwQGcd9CrysLv4wTyoLFD90dxqbp1EgdPRB7Kskznea6Zn/aPoKoqUUrJOI5m4l2QBfSyLHKep1zXZSae3An1fS/7vst931bGkzuhaZrsLVbGkzuheZ7lOI6HyJ2QUkqv6yrbtv0LT+6E7G0UrfBfP3lZlpoXH4ZBmHgn5Pv+KwxDfqp0XQdgJp6c/RsUBIGOokiSJDE/s21bACbe5Ozp0TdAHMdSFIXUdS1N01C2wpObPT36HifwCJzI0iX29Oh7XP0E3CB9L01TzM+i/wePv4ZE5RtAngAAAABJRU5ErkJggg==) 10px center no-repeat;
60
  content: '';
61
  display: block;
62
  width: 31px;
63
64
  position: absolute;
65
  bottom: 0;
66
  left: -3px;
67
  top: 0;
68
  z-index: 10;
69
}
70
71
/*  Icon background */
72
.persona-button span:before{
73
  content: '';
74
  display: block;
75
  height: 100%;
76
  width: 20px;
77
78
  position: absolute;
79
  bottom: 0;
80
  left: 0;
81
  top: 0;
82
  z-index: 1;
83
84
  background: #42a9dd;
85
  background: -moz-linear-gradient(top, #50b8e8, #3095ce);
86
  background: -ms-linear-gradient(top, #50b8e8, #3095ce);
87
  background: -o-linear-gradient(top, #50b8e8, #3095ce);
88
  background: -webkit-linear-gradient(top, #50b8e8, #3095ce);
89
  background: linear-gradient(top, #50b8e8, #3095ce);
90
91
  -moz-border-radius:   3px 0 0 3px;
92
  -ms-border-radius:     3px 0 0 3px;
93
  -o-border-radius:     3px 0 0 3px;
94
  -webkit-border-radius:   3px 0 0 3px;
95
  border-radius:       3px 0 0 3px;
96
}
97
98
/* Triangle */
99
.persona-button:before{
100
  background: #42a9dd;
101
  content: '';
102
  display: block;
103
  height: 26px;
104
  width: 26px;
105
106
  position: absolute;
107
  left: 2px;
108
  top: 50%;
109
  margin-top: -13px;
110
  z-index: 0;
111
112
  background: -moz-linear-gradient(-45deg, #50b8e8, #3095ce);
113
  background: -ms-linear-gradient(-45deg, #50b8e8, #3095ce);
114
  background: -o-linear-gradient(-45deg, #50b8e8, #3095ce);
115
  background: -webkit-linear-gradient(-45deg, #50b8e8, #3095ce);
116
  background: linear-gradient(-45deg, #3095ce, #50b8e8); /* flipped for updated spec */
117
118
  -moz-box-shadow:   1px -1px 1px rgba(0,0,0,0.1);
119
  -ms-box-shadow:   1px -1px 1px rgba(0,0,0,0.1);
120
  -o-box-shadow:     1px -1px 1px rgba(0,0,0,0.1);
121
  -webkit-box-shadow: 1px -1px 1px rgba(0,0,0,0.1);
122
  box-shadow:     1px -1px 1px rgba(0,0,0,0.1);
123
124
  -moz-transform:   rotate(45deg);
125
  -ms-transform:     rotate(45deg);
126
  -o-transform:     rotate(45deg);
127
  -webkit-transform:   rotate(45deg);
128
  transform:       rotate(45deg);
129
}
130
131
/* Inset shadow (required here because the icon background clips it when on the `a` element) */
132
.persona-button:after{
133
  content: '';
134
  display: block;
135
  height: 100%;
136
  width: 100%;
137
138
  position: absolute;
139
  left: 0;
140
  top: 0;
141
  bottom: 0;
142
  right: 0;
143
  z-index: 10;
144
145
  -moz-border-radius:   3px;
146
  -ms-border-radius:     3px;
147
  -o-border-radius:     3px;
148
  -webkit-border-radius:   3px;
149
  border-radius:       3px;
150
151
  -moz-box-shadow:   inset 0 -1px 0 rgba(0,0,0,0.3);
152
  -ms-box-shadow:   inset 0 -1px 0 rgba(0,0,0,0.3);
153
  -o-box-shadow:     inset 0 -1px 0 rgba(0,0,0,0.3);
154
  -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,0.3);
155
  box-shadow:     inset 0 -1px 0 rgba(0,0,0,0.3);
156
}
157
158
/* ========================================================
159
 *    Dark button 
160
 * ===================================================== */
161
.persona-button.dark{
162
  background: #3c3c3c;
163
  background: -moz-linear-gradient(top, #606060, #3c3c3c);
164
  background: -ms-linear-gradient(top, #606060, #3c3c3c);
165
  background: -o-linear-gradient(top, #606060, #3c3c3c);
166
  background: -webkit-linear-gradient(top, #606060, #3c3c3c);
167
  background: linear-gradient(top, #606060, #3c3c3c);
168
}
169
.persona-button.dark:hover{
170
  background: #2d2d2d;
171
  background: -moz-linear-gradient(top, #484848, #2d2d2d);
172
  background: -ms-linear-gradient(top, #484848, #2d2d2d);
173
  background: -o-linear-gradient(top, #484848, #2d2d2d);
174
  background: -webkit-linear-gradient(top, #484848, #2d2d2d);
175
  background: linear-gradient(top, #484848, #2d2d2d);
176
}
177
.persona-button.dark span:before{ /* Icon BG */
178
  background: #d34f2d;
179
  background: -moz-linear-gradient(top, #ebac45, #d34f2d);
180
  background: -ms-linear-gradient(top, #ebac45, #d34f2d);
181
  background: -o-linear-gradient(top, #ebac45, #d34f2d);
182
  background: -webkit-linear-gradient(top, #ebac45, #d34f2d);
183
  background: linear-gradient(top, #ebac45, #d34f2d);
184
}
185
.persona-button.dark:before{ /* Triangle */
186
  background: #d34f2d;
187
  background: -moz-linear-gradient(-45deg, #ebac45, #d34f2d);
188
  background: -ms-linear-gradient(-45deg, #ebac45, #d34f2d);
189
  background: -o-linear-gradient(-45deg, #ebac45, #d34f2d);
190
  background: -webkit-linear-gradient(-45deg, #ebac45, #d34f2d);
191
  background: linear-gradient(-45deg, #d34f2d, #ebac45); /* flipped for updated spec */
192
}
193
194
/* ========================================================
195
 *    Orange button 
196
 * ===================================================== */
197
.persona-button.orange{
198
  background: #ee731a;
199
  background: -moz-linear-gradient(top, #ee731a, #d03116);
200
  background: -ms-linear-gradient(top, #ee731a, #d03116);
201
  background: -o-linear-gradient(top, #ee731a, #d03116);
202
  background: -webkit-linear-gradient(top, #ee731a, #d03116);
203
  background: linear-gradient(top, #ee731a, #d03116);
204
}
205
.persona-button.orange:hover{
206
  background: #cb6216;
207
  background: -moz-linear-gradient(top, #cb6216, #b12a13);
208
  background: -ms-linear-gradient(top, #cb6216, #b12a13);
209
  background: -o-linear-gradient(top, #cb6216, #b12a13);
210
  background: -webkit-linear-gradient(top, #cb6216, #b12a13);
211
  background: linear-gradient(top, #cb6216, #b12a13);
212
}
213
.persona-button.orange span:before{ /* Icon BG */
214
  background: #e84a21;
215
  background: -moz-linear-gradient(top, #f7ad27, #e84a21);
216
  background: -ms-linear-gradient(top, #f7ad27, #e84a21);
217
  background: -o-linear-gradient(top, #f7ad27, #e84a21);
218
  background: -webkit-linear-gradient(top, #f7ad27, #e84a21);
219
  background: linear-gradient(top, #f7ad27, #e84a21);
220
}
221
.persona-button.orange:before{ /* Triangle */
222
  background: #e84a21;
223
  background: -moz-linear-gradient(-45deg, #f7ad27, #e84a21);
224
  background: -ms-linear-gradient(-45deg, #f7ad27, #e84a21);
225
  background: -o-linear-gradient(-45deg, #f7ad27, #e84a21);
226
  background: -webkit-linear-gradient(-45deg, #f7ad27, #e84a21);
227
  background: linear-gradient(-45deg, #e84a21, #f7ad27); /* flipped for updated spec */
228
}
(-)a/koha-tmpl/opac-tmpl/prog/en/includes/doc-head-close.inc (+3 lines)
Lines 20-25 Link Here
20
    <link rel="stylesheet" type="text/css" href="[% themelang %]/css/[% opac_css_override %]" />
20
    <link rel="stylesheet" type="text/css" href="[% themelang %]/css/[% opac_css_override %]" />
21
[% END %]
21
[% END %]
22
<link rel="stylesheet" type="text/css" media="print" href="[% themelang %]/css/print.css" />
22
<link rel="stylesheet" type="text/css" media="print" href="[% themelang %]/css/print.css" />
23
[% IF persona %]
24
 <link rel="stylesheet" type="text/css" href="[% themelang %]/css/persona-buttons.css" />
25
[% END %]
23
[% IF ( OPACMobileUserCSS ) %]<style type="text/css" media="screen and (max-width:700px)">[% OPACMobileUserCSS %]</style>[% END %]
26
[% IF ( OPACMobileUserCSS ) %]<style type="text/css" media="screen and (max-width:700px)">[% OPACMobileUserCSS %]</style>[% END %]
24
[% IF ( OPACUserCSS ) %]<style type="text/css">[% OPACUserCSS %]</style>[% END %]
27
[% IF ( OPACUserCSS ) %]<style type="text/css">[% OPACUserCSS %]</style>[% END %]
25
<!-- yui js --> 
28
<!-- yui js --> 
(-)a/koha-tmpl/opac-tmpl/prog/en/includes/masthead.inc (-1 / +1 lines)
Lines 10-16 Link Here
10
            [% IF ( ShowOpacRecentSearchLink ) %]
10
            [% IF ( ShowOpacRecentSearchLink ) %]
11
                <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>
11
                <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>
12
            [% END %]
12
            [% END %]
13
			[% IF ( loggedinusername ) %]<li><a class="logout" id="logout" href="/cgi-bin/koha/opac-main.pl?logout.x=1">Log Out</a></li>[% END %]
13
			[% IF ( loggedinusername ) %]<li><a class="logout" id="logout" href="/cgi-bin/koha/opac-main.pl?logout.x=1" [% IF persona %] onclick='navigator.id.logout();'[% END %]>Log Out</a></li>[% END %]
14
   	</ul>	
14
   	</ul>	
15
  [% END %]
15
  [% END %]
16
</div>
16
</div>
(-)a/koha-tmpl/opac-tmpl/prog/en/includes/opac-bottom.inc (+36 lines)
Lines 60-64 Link Here
60
60
61
[% END %]
61
[% END %]
62
62
63
[% IF persona %]
64
<script src="https://login.persona.org/include.js"></script>
65
<script type="text/javascript" language="javascript">
66
67
navigator.id.watch({
68
    loggedInUser: [% IF emailaddress %]'[% emailaddress %]'[% ELSE %]null[% END %],
69
    onlogin: function (assertion) {
70
        $.post('/cgi-bin/koha/svc/login',
71
            { assertion: assertion },
72
            function (data) {
73
                window.location = '/cgi-bin/koha/opac-user.pl';
74
            }
75
        );
76
    },
77
    onlogout: function () {
78
        window.location = '/cgi-bin/koha/opac-main.pl?logout.x=1';
79
    }
80
});
81
82
var signinLink = document.getElementById('browserid');
83
84
if (signinLink) {
85
    signinLink.onclick = function(evt) {
86
        // Requests a signed identity assertion from the user.
87
        navigator.id.request({
88
            siteName: "[% LibraryName | html %]",
89
            returnTo: '/cgi-bin/koha/opac-user.pl',
90
            oncancel: function() { alert('user refuses to share identity.'); }
91
            });
92
        };
93
}
94
95
</script>
96
[% END %]
97
							
98
63
</body>
99
</body>
64
</html>
100
</html>
(-)a/koha-tmpl/opac-tmpl/prog/en/js/browserid_include.js (+1 lines)
Line 0 Link Here
1
(function(){var a=function(){function e(a){return Array.isArray?Array.isArray(a):a.constructor.toString().indexOf("Array")!=-1}function d(a,c,d){var e=b[c][d];for(var f=0;f<e.length;f++)e[f].win===a&&e.splice(f,1);b[c][d].length===0&&delete b[c][d]}function c(a,c,d,e){function f(b){for(var c=0;c<b.length;c++)if(b[c].win===a)return!0;return!1}var g=!1;if(c==="*")for(var h in b){if(!b.hasOwnProperty(h))continue;if(h==="*")continue;if(typeof b[h][d]=="object"){g=f(b[h][d]);if(g)break}}else b["*"]&&b["*"][d]&&(g=f(b["*"][d])),!g&&b[c]&&b[c][d]&&(g=f(b[c][d]));if(g)throw"A channel is already bound to the same window which overlaps with origin '"+c+"' and has scope '"+d+"'";typeof b[c]!="object"&&(b[c]={}),typeof b[c][d]!="object"&&(b[c][d]=[]),b[c][d].push({win:a,handler:e})}"use strict";var a=Math.floor(Math.random()*1000001),b={},f={},g=function(a){try{var c=JSON.parse(a.data);if(typeof c!="object"||c===null)throw"malformed"}catch(a){return}var d=a.source,e=a.origin,g,h,i;if(typeof c.method=="string"){var j=c.method.split("::");j.length==2?(g=j[0],i=j[1]):i=c.method}typeof c.id!="undefined"&&(h=c.id);if(typeof i=="string"){var k=!1;if(b[e]&&b[e][g])for(var h=0;h<b[e][g].length;h++)if(b[e][g][h].win===d){b[e][g][h].handler(e,i,c),k=!0;break}if(!k&&b["*"]&&b["*"][g])for(var h=0;h<b["*"][g].length;h++)if(b["*"][g][h].win===d){b["*"][g][h].handler(e,i,c);break}}else typeof h!="undefined"&&f[h]&&f[h](e,i,c)};window.addEventListener?window.addEventListener("message",g,!1):window.attachEvent&&window.attachEvent("onmessage",g);return{build:function(b){var g=function(a){if(b.debugOutput&&window.console&&window.console.log){try{typeof a!="string"&&(a=JSON.stringify(a))}catch(c){}console.log("["+j+"] "+a)}};if(!window.postMessage)throw"jschannel cannot run this browser, no postMessage";if(!window.JSON||!window.JSON.stringify||!window.JSON.parse)throw"jschannel cannot run this browser, no JSON parsing/serialization";if(typeof b!="object")throw"Channel build invoked without a proper object argument";if(!b.window||!b.window.postMessage)throw"Channel.build() called without a valid window argument";if(window===b.window)throw"target window is same as present window -- not allowed";var h=!1;if(typeof b.origin=="string"){var i;b.origin==="*"?h=!0:null!==(i=b.origin.match(/^https?:\/\/(?:[-a-zA-Z0-9_\.])+(?::\d+)?/))&&(b.origin=i[0].toLowerCase(),h=!0)}if(!h)throw"Channel.build() called with an invalid origin";if(typeof b.scope!="undefined"){if(typeof b.scope!="string")throw"scope, when specified, must be a string";if(b.scope.split("::").length>1)throw"scope may not contain double colons: '::'"}var j=function(){var a="",b="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";for(var c=0;c<5;c++)a+=b.charAt(Math.floor(Math.random()*b.length));return a}(),k={},l={},m={},n=!1,o=[],p=function(a,b,c){var d=!1,e=!1;return{origin:b,invoke:function(b,d){if(!m[a])throw"attempting to invoke a callback of a nonexistent transaction: "+a;var e=!1;for(var f=0;f<c.length;f++)if(b===c[f]){e=!0;break}if(!e)throw"request supports no such callback '"+b+"'";t({id:a,callback:b,params:d})},error:function(b,c){e=!0;if(!m[a])throw"error called for nonexistent message: "+a;delete m[a],t({id:a,error:b,message:c})},complete:function(b){e=!0;if(!m[a])throw"complete called for nonexistent message: "+a;delete m[a],t({id:a,result:b})},delayReturn:function(a){typeof a=="boolean"&&(d=a===!0);return d},completed:function(){return e}}},q=function(a,b,c){return window.setTimeout(function(){if(l[a]){var d="timeout ("+b+"ms) exceeded on method '"+c+"'";(1,l[a].error)("timeout_error",d),delete l[a],delete f[a]}},b)},r=function(a,c,d){if(typeof b.gotMessageObserver=="function")try{b.gotMessageObserver(a,d)}catch(h){g("gotMessageObserver() raised an exception: "+h.toString())}if(d.id&&c){if(k[c]){var i=p(d.id,a,d.callbacks?d.callbacks:[]);m[d.id]={};try{if(d.callbacks&&e(d.callbacks)&&d.callbacks.length>0)for(var j=0;j<d.callbacks.length;j++){var n=d.callbacks[j],o=d.params,q=n.split("/");for(var r=0;r<q.length-1;r++){var s=q[r];typeof o[s]!="object"&&(o[s]={}),o=o[s]}o[q[q.length-1]]=function(){var a=n;return function(b){return i.invoke(a,b)}}()}var t=k[c](i,d.params);!i.delayReturn()&&!i.completed()&&i.complete(t)}catch(h){var u="runtime_error",v=null;typeof h=="string"?v=h:typeof h=="object"&&(h&&e(h)&&h.length==2?(u=h[0],v=h[1]):typeof h.error=="string"&&(u=h.error,h.message?typeof h.message=="string"?v=h.message:h=h.message:v=""));if(v===null)try{v=JSON.stringify(h),typeof v=="undefined"&&(v=h.toString())}catch(w){v=h.toString()}i.error(u,v)}}}else d.id&&d.callback?!l[d.id]||!l[d.id].callbacks||!l[d.id].callbacks[d.callback]?g("ignoring invalid callback, id:"+d.id+" ("+d.callback+")"):l[d.id].callbacks[d.callback](d.params):d.id?l[d.id]?(d.error?(1,l[d.id].error)(d.error,d.message):d.result!==undefined?(1,l[d.id].success)(d.result):(1,l[d.id].success)(),delete l[d.id],delete f[d.id]):g("ignoring invalid response: "+d.id):c&&k[c]&&k[c](null,d.params)};c(b.window,b.origin,typeof b.scope=="string"?b.scope:"",r);var s=function(a){typeof b.scope=="string"&&b.scope.length&&(a=[b.scope,a].join("::"));return a},t=function(a,c){if(!a)throw"postMessage called with null message";var d=n?"post  ":"queue ";g(d+" message: "+JSON.stringify(a));if(!c&&!n)o.push(a);else{if(typeof b.postMessageObserver=="function")try{b.postMessageObserver(b.origin,a)}catch(e){g("postMessageObserver() raised an exception: "+e.toString())}b.window.postMessage(JSON.stringify(a),b.origin)}},u=function(a,c){g("ready msg received");if(n)throw"received ready message while in ready state.  help!";c==="ping"?j+="-R":j+="-L",v.unbind("__ready"),n=!0,g("ready msg accepted."),c==="ping"&&v.notify({method:"__ready",params:"pong"});while(o.length)t(o.pop());typeof b.onReady=="function"&&b.onReady(v)},v={unbind:function(a){if(k[a]){if(delete k[a])return!0;throw"can't delete method: "+a}return!1},bind:function(a,b){if(!a||typeof a!="string")throw"'method' argument to bind must be string";if(!b||typeof b!="function")throw"callback missing from bind params";if(k[a])throw"method '"+a+"' is already bound!";k[a]=b;return this},call:function(b){if(!b)throw"missing arguments to call function";if(!b.method||typeof b.method!="string")throw"'method' argument to call must be string";if(!b.success||typeof b.success!="function")throw"'success' callback missing from call";var c={},d=[],e=function(a,b){if(typeof b=="object")for(var f in b){if(!b.hasOwnProperty(f))continue;var g=a+(a.length?"/":"")+f;typeof b[f]=="function"?(c[g]=b[f],d.push(g),delete b[f]):typeof b[f]=="object"&&e(g,b[f])}};e("",b.params);var g={id:a,method:s(b.method),params:b.params};d.length&&(g.callbacks=d),b.timeout&&q(a,b.timeout,s(b.method)),l[a]={callbacks:c,error:b.error,success:b.success},f[a]=r,a++,t(g)},notify:function(a){if(!a)throw"missing arguments to notify function";if(!a.method||typeof a.method!="string")throw"'method' argument to notify must be string";t({method:s(a.method),params:a.params})},destroy:function(){d(b.window,b.origin,typeof b.scope=="string"?b.scope:""),window.removeEventListener?window.removeEventListener("message",r,!1):window.detachEvent&&window.detachEvent("onmessage",r),n=!1,k={},m={},l={},b.origin=null,o=[],g("channel destroyed"),j=""}};v.bind("__ready",u),setTimeout(function(){},0);return v}}}();WinChan=function(){function j(){var b=window.location,c=window.opener.frames,d=b.protocol+"//"+b.host;for(i=c.length-1;i>=0;i++)try{if(c[i].location.href.indexOf(d)===0&&c[i].name===a)return c[i]}catch(e){}return}function h(a){/^https?:\/\//.test(a)||(a=window.location.href);var b=/^(https?:\/\/[-_a-zA-Z\.0-9:]+)/.exec(a);return b?b[1]:a}function g(){return window.JSON&&window.JSON.stringify&&window.JSON.parse&&window.postMessage}function f(){try{return d.indexOf("Fennec/")!=-1||d.indexOf("Firefox/")!=-1&&d.indexOf("Android")!=-1}catch(a){}return!1}function e(){var a=-1;if(navigator.appName=="Microsoft Internet Explorer"){var b=navigator.userAgent,c=new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})");c.exec(b)!=null&&(a=parseFloat(RegExp.$1))}return a>=8}function c(a,b,c){a.detachEvent?a.detachEvent("on"+b,c):a.removeEventListener&&a.removeEventListener(b,c,!1)}function b(a,b,c){a.attachEvent?a.attachEvent("on"+b,c):a.addEventListener&&a.addEventListener(b,c,!1)}var a="__winchan_relay_frame",k=e();return g()?{open:function(d,e){function p(a){try{var b=JSON.parse(a.data);b.a==="ready"?l.postMessage(n,j):b.a==="error"?e&&(e(b.d),e=null):b.a==="response"&&(c(window,"message",p),c(window,"unload",o),o(),e&&(e(null,b.d),e=null))}catch(a){}}function o(){i&&document.body.removeChild(i),i=undefined,m&&m.close(),m=undefined}if(!e)throw"missing required callback argument";var g;d.url||(g="missing required 'url' parameter"),d.relay_url||(g="missing required 'relay_url' parameter"),g&&setTimeout(function(){e(g)},0);if(!d.window_features||f())d.window_features=undefined;var i,j=h(d.url);if(j!==h(d.relay_url))return setTimeout(function(){e("invalid arguments: origin of url and relay_url must match")},0);var l;k&&(i=document.createElement("iframe"),i.setAttribute("src",d.relay_url),i.style.display="none",i.setAttribute("name",a),document.body.appendChild(i),l=i.contentWindow);var m=window.open(d.url,null,d.window_features);l||(l=m);var n=JSON.stringify({a:"request",d:d.params});b(window,"unload",o),b(window,"message",p);return{close:o,focus:function(){if(m)try{m.focus()}catch(a){}}}}}:{open:function(a,b,c,d){setTimeout(function(){d("unsupported browser")},0)}}}();var b=function(){function l(){return c}function k(){c=g()||h()||i()||j();return!c}function j(){if(!(window.JSON&&window.JSON.stringify&&window.JSON.parse))return"JSON_NOT_SUPPORTED"}function i(){if(!a.postMessage)return"POSTMESSAGE_NOT_SUPPORTED"}function h(){try{var b="localStorage"in a&&a.localStorage!==null;if(b)a.localStorage.setItem("test","true"),a.localStorage.removeItem("test");else return"LOCALSTORAGE_NOT_SUPPORTED"}catch(c){return"LOCALSTORAGE_DISABLED"}}function g(){return f()}function f(){var a=e(),b=a>-1&&a<8;if(b)return"BAD_IE_VERSION"}function e(){var a=-1;if(b.appName=="Microsoft Internet Explorer"){var c=b.userAgent,d=new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})");d.exec(c)!=null&&(a=parseFloat(RegExp.$1))}return a}function d(c,d){b=c,a=d}var a=window,b=navigator,c;return{setTestEnv:d,isSupported:k,getNoSupportReason:l}}();navigator.id||(navigator.id={});if(!navigator.id.request||navigator.id._shimmed){var c="https://browserid.org",d=navigator.userAgent,e=d.indexOf("Fennec/")!=-1||d.indexOf("Firefox/")!=-1&&d.indexOf("Android")!=-1,f=e?undefined:"menubar=0,location=1,resizable=1,scrollbars=1,status=0,dialog=1,width=700,height=375",g,h={login:null,logout:null,ready:null},j=undefined;function k(a){a!==!0;if(j===undefined)j=a;else if(j!=a)throw"you cannot combine the navigator.id.watch() API with navigator.id.getVerifiedEmail() or navigator.id.get()this site should instead use navigator.id.request() and navigator.id.watch()"}var l,m=b.isSupported();function n(){if(!!m)try{if(!l){var b=window.document,d=b.createElement("iframe");d.style.display="none",b.body.appendChild(d),d.src=c+"/communication_iframe",l=a.build({window:d.contentWindow,origin:c,scope:"mozid_ni",onReady:function(){l.call({method:"loaded",success:function(){h.ready&&h.ready()},error:function(){}})}}),l.bind("logout",function(a,b){h.logout&&h.logout()}),l.bind("login",function(a,b){h.login&&h.login(b)})}}catch(e){l=undefined}}function o(a){if(typeof a=="object"){if(a.onlogin&&typeof a.onlogin!="function"||a.onlogout&&typeof a.onlogout!="function"||a.onready&&typeof a.onready!="function")throw"non-function where function expected in parameters to navigator.id.watch()";if(!a.onlogin)throw"'onlogin' is a required argument to navigator.id.watch()";if(!a.onlogout)throw"'onlogout' is a required argument to navigator.id.watch()";h.login=a.onlogin||null,h.logout=a.onlogout||null,h.ready=a.onready||null,n(),typeof a.loggedInEmail!="undefined"&&l&&l.notify({method:"loggedInUser",params:a.loggedInEmail})}}function p(a){if(g)try{g.focus()}catch(d){}else{if(!b.isSupported()){var e=b.getNoSupportReason(),i="unsupported_dialog";e==="LOCALSTORAGE_DISABLED"&&(i="cookies_disabled"),g=window.open(c+"/"+i,null,f);return}l&&l.notify({method:"dialog_running"}),g=WinChan.open({url:c+"/sign_in",relay_url:c+"/relay",window_features:f,params:{method:"get",params:a}},function(b,c){l&&(!b&&c&&c.email&&l.notify({method:"loggedInUser",params:c.email}),l.notify({method:"dialog_complete"})),g=undefined;if(!b&&c&&c.assertion)try{h.login&&h.login(c.assertion)}catch(d){}if(b==="client closed window"||!c)a&&a.oncancel&&a.oncancel(),delete a.oncancel})}}navigator.id={request:function(a){a=a||{},k(!1);return p(a)},watch:function(a){k(!1),o(a)},logout:function(a){n(),l&&l.notify({method:"logout"}),typeof a=="function"&&setTimeout(a,0)},get:function(a,b){b=b||{},k(!0),o({onlogin:function(b){a&&(a(b),a=null)},onlogout:function(){}}),b.oncancel=function(){a&&(a(null),a=null),h.login=h.logout=h.ready=null},b&&b.silent?a&&setTimeout(function(){a(null)},0):p(b)},getVerifiedEmail:function(a){k(!0),navigator.id.get(a)},_shimmed:!0}}})()
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-auth.tt (-1 / +7 lines)
Lines 99-105 please choose against which one you would like to authenticate: </p> Link Here
99
          <a href="mailto:[% admin %]">email the Koha Administrator</a>.</li>
99
          <a href="mailto:[% admin %]">email the Koha Administrator</a>.</li>
100
  <li>Use top menu bar to navigate to another part of Koha.</li>
100
  <li>Use top menu bar to navigate to another part of Koha.</li>
101
</ul>
101
</ul>
102
[% END %]</div>
102
[% END %]
103
104
[% IF persona %]
105
<a href="#" class="persona-button" id="browserid" ><span>Sign in with your Email</span></a>
106
[% END %]
107
108
</div>
103
</div>
109
</div>
104
</div>
110
</div>
105
</div>
111
</div>
(-)a/koha-tmpl/opac-tmpl/prog/en/modules/opac-main.tt (+3 lines)
Lines 63-68 Link Here
63
	</form>
63
	</form>
64
	</div>
64
	</div>
65
    [% END %]
65
    [% END %]
66
    [% IF persona %]
67
     <a href="#" class="persona-button" id="browserid" ><span>Sign in with your Email</span></a>
68
    [% END %]
66
    [% END %]
69
    [% END %]
67
    [% END %]
70
    [% END %]
68
    [% IF ( OpacNavRight ) %]<div id="opacrightsidebar" class="container">[% OpacNavRight %]</div>[% END %]
71
    [% IF ( OpacNavRight ) %]<div id="opacrightsidebar" class="container">[% OpacNavRight %]</div>[% END %]
(-)a/opac/svc/login (-1 / +52 lines)
Line 0 Link Here
0
- 
1
#!/usr/bin/perl
2
3
# Copyright chris@bigballofwax.co.nz 2013 
4
#
5
# This file is part of Koha.
6
#
7
# Koha is free software; you can redistribute it and/or modify it under the
8
# terms of the GNU General Public License as published by the Free Software
9
# Foundation; either version 3 of the License, or (at your option) any later
10
# version.
11
#
12
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License along
17
# with Koha; if not, write to the Free Software Foundation, Inc.,
18
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20
use CGI;
21
use strict;
22
use warnings;
23
use C4::Auth;
24
use C4::Context;
25
26
use LWP::UserAgent;
27
use HTTP::Request::Common qw{ POST };
28
use JSON qw( decode_json );
29
30
my $url  = 'https://verifier.login.persona.org/verify';
31
32
my $query = CGI->new();
33
34
my $host = C4::Context->preference('OPACBaseURL');
35
36
my $assertion = $query->param('assertion');
37
38
my $ua = LWP::UserAgent->new();
39
my $response =
40
  $ua->post( $url, [ 'assertion' => $assertion, 'audience' => $host ] );
41
42
if ( $response->is_success ) {
43
    my $content      = $response->decoded_content();
44
    my $decoded_json = decode_json($content);
45
    my ( $userid, $cookie, $sessionID ) =
46
      checkauth( $query, 1,  { borrow => 1 }, 'opac', $decoded_json->{'email'} );
47
    print $query->header( -cookie => $cookie );
48
    print $decoded_json;
49
}
50
else {
51
    warn $response->status_line, "\n";
52
}

Return to bug 9587