Bug 36197: (QA follow-up): Adopt POST REDIRECT GET pattern

Upon submitting the unauthenticated request, the user is now redirected to a different page and the request details are passed through a session variable. This is to prevent the user from being able to resubmit the same unauthenticated request multiple times (see security bug 39611)

Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>
Signed-off-by: Katrin Fischer <katrin.fischer@bsz-bw.de>
This commit is contained in:
Pedro Amorim 2025-04-11 14:12:18 +00:00 committed by Katrin Fischer
parent e677ba112f
commit 8c35c83272
No known key found for this signature in database
GPG Key ID: 0EF6E2C03357A834
4 changed files with 170 additions and 75 deletions

View File

@ -64,10 +64,6 @@
<div class="col-lg-2">
<div id="navigation"> [% INCLUDE 'navigation.inc' IsPatronPage=1 %] </div>
</div>
[% ELSIF (!logged_in_user) %]
<div class="col-lg-2">
<div id="navigation"> </div>
</div>
[% END %]
[% SET column_class = "col order-first order-md-first order-lg-2" %]
@ -252,76 +248,6 @@
</fieldset>
[% END %]
</form>
[% ELSIF op == 'unauth_view' %]
<div class="alert alert-success" role="alert">Your request has been placed. We'll contact you shortly.</div>
<h1>View interlibrary loan request</h1>
[% INCLUDE messages %]
[% status = request.status %]
<fieldset class="rows">
<legend id="library_legend">Details from library</legend>
<ol>
[% type = request.get_type %]
<li>
<label for="request_id">Request ID:</label>
[% request.id | html %]
</li>
<li>
<label for="backend">Requested from:</label>
[% request.backend | html %]
</li>
[% IF request.biblio_id %]
<li>
<label for="biblio">Requested item:</label>
<a href="/cgi-bin/koha/opac-detail.pl?biblionumber=[% request.biblio_id | uri %]">View the requested item</a>
</li>
[% END %]
<li>
<label for="branchcode">Collection library:</label>
[% Branches.GetName(request.branchcode) | html %]
</li>
<li>
<label for="status">Status:</label>
[% request.status_alias ? request.statusalias.lib_opac : request.capabilities.$status.name | html %]
</li>
<li>
<label for="medium">Request type:</label>
[% IF type %][% type | html %][% ELSE %]<span>N/A</span>[% END %]
</li>
<li>
<label for="placed">Request placed:</label>
[% request.placed | $KohaDates %]
</li>
<li>
<label for="updated">Last updated:</label>
[% request.updated | $KohaDates %]
</li>
<li>
<label for="unauthenticated_first_name">Unauthenticated first name:</label>
[% request.extended_attributes.find({'type'=>'unauthenticated_first_name'}).value | html %]
</li>
<li>
<label for="unauthenticated_last_name">Unauthenticated last name:</label>
[% request.extended_attributes.find({'type'=>'unauthenticated_last_name'}).value | html %]
</li>
<li>
<label for="unauthenticated_email">Unauthenticated email:</label>
[% request.extended_attributes.find({'type'=>'unauthenticated_email'}).value | html %]
</li>
<li>
<label for="notesopac">Notes:</label>
[% request.notesopac | html %]
</li>
</ol>
</fieldset>
<div id="ill-supplier-metadata" class="rows">
<legend id="backend_legend">Details from [% request.backend | html %]</legend>
[% FOREACH meta IN request.metadata %]
<div class="requestattr-[% meta.key | replace(' ', '_') | html %]">
<span class="label">[% meta.key | html %]:</span>
<span class="value">[% IF meta.value %][% meta.value | html %][% ELSE %]N/A[% END %]</span>
</div>
[% END %]
</div>
[% ELSIF op == 'availability' %]
<h1>Interlibrary loan item availability</h1>
<div id="results">

View File

@ -0,0 +1,115 @@
[% USE raw %]
[% USE KohaDates %]
[% USE Branches %]
[% USE AdditionalContents %]
[% SET OpacNav = AdditionalContents.get( location => "OpacNav", lang => lang, library => logged_in_user.branchcode || default_branch, blocktitle => 0 ) %]
[% INCLUDE 'doc-head-open.inc' %]
<title>ILL requests</title>
[% INCLUDE 'doc-head-close.inc' %]
[% BLOCK cssinclude %]
[% END %]
[% INCLUDE 'bodytag.inc' bodyid='opac-illrequests' %]
[% INCLUDE 'masthead.inc' %]
<div class="main">
[% WRAPPER breadcrumbs %]
[% IF op != 'list' %]
[% WRAPPER breadcrumb_item %]
<a href="/cgi-bin/koha/opac-illrequests.pl">Interlibrary loan requests</a>
[% END %]
[% END %]
[% END #/ WRAPPER breadcrumbs %]
<div class="container-fluid">
<div class="row">
<div class="col-lg-2">
[% IF op == 'list' %]
<h1>Interlibrary loan requests</h1>
[% ELSIF op == 'view' %]
<h1>View interlibrary loan request</h1>
[% ELSIF op == 'unauth_view' %]
<h1>View interlibrary loan request</h1>
[% ELSIF op == 'availability' %]
<h1>Interlibrary loan item availability</h1>
[% ELSIF op == 'typedisclaimer' %]
<h1>ILL request disclaimer</h1>
[% ELSIF op == 'confirmautoill' %]
<h1>Confirming request</h1>
[% END %]
</div>
[% SET column_class = "col order-first order-md-first order-lg-2" %]
[% IF ( OpacNav||loggedinusername ) %]
[% column_class = "col-lg-10 order-first order-md-first order-lg-2" %]
[% END %]
<div class="[% column_class | html %]">
<div class="maincontent">
<div class="alert alert-success" role="alert">Your request has been placed. We'll contact you shortly.</div>
<h1>View interlibrary loan request</h1>
[% status = request.status %]
<fieldset class="rows">
<legend id="library_legend">Details from library</legend>
<ol>
[% type = request.get_type %]
<li>
<label for="request_id">Request ID:</label>
[% request.illrequest_id | html %]
</li>
<li>
<label for="backend">Requested from:</label>
[% request.backend | html %]
</li>
<li>
<label for="branchcode">Collection library:</label>
[% Branches.GetName(request.branchcode) | html %]
</li>
<li>
<label for="status">Status:</label>
[% request.status | html %]
</li>
<li>
<label for="medium">Request type:</label>
[% IF type %][% type | html %][% ELSE %]<span>N/A</span>[% END %]
</li>
<li>
<label for="placed">Request placed:</label>
[% request.placed | $KohaDates %]
</li>
<li>
<label for="updated">Last updated:</label>
[% request.updated | $KohaDates %]
</li>
<li>
<label for="unauthenticated_first_name">Unauthenticated first name:</label>
[% request.unauthenticated_first_name | html %]
</li>
<li>
<label for="unauthenticated_last_name">Unauthenticated last name:</label>
[% request.unauthenticated_last_name | html %]
</li>
<li>
<label for="unauthenticated_email">Unauthenticated email:</label>
[% request.unauthenticated_email| html %]
</li>
</ol>
</fieldset>
<div id="ill-supplier-metadata" class="rows">
<legend id="backend_legend">Request details</legend>
[% FOREACH meta IN request.metadata %]
[% IF meta.value %]
<div class="requestattr-[% meta.key | replace(' ', '_') | html %]">
<span class="label">[% meta.key | html %]:</span>
<span class="value">[% meta.value | html %]</span>
</div>
[% END %]
[% END %]
</div>
</div>
</div>
</div>
</div>
</div>
[% INCLUDE 'opac-bottom.inc' %]
[% BLOCK jsinclude %]
[% END %]

View File

@ -0,0 +1,30 @@
#!/usr/bin/perl
use Modern::Perl;
use JSON qw( decode_json );
use CGI qw ( -utf8 );
use C4::Auth qw( get_template_and_user );
use C4::Output qw( output_html_with_http_headers );
use URI::Escape qw( uri_unescape );
my $query = CGI->new;
my $sessionID = $query->cookie('CGISESSID');
my $session = C4::Auth::get_session($sessionID);
my $request =
eval { decode_json( uri_unescape( $session->param('ill_request_unauthenticated') ) ) };
my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
{
template_name => "opac-illrequests_unauthenticated.tt",
query => $query,
type => "opac",
authnotrequired => 1,
}
);
$template->param( request => $request );
output_html_with_http_headers $query, $cookie, $template->output;

View File

@ -28,6 +28,7 @@ use C4::Output qw( output_html_with_http_headers );
use Digest::MD5 qw( md5_base64 );
use POSIX qw( strftime );
use String::Random qw( random_string );
use URI::Escape qw( uri_escape );
use Koha::ILL::Request::Config;
use Koha::ILL::Requests;
@ -197,7 +198,30 @@ if ( $op eq 'list' ) {
$type_disclaimer->after_request_created( $params, $request );
}
if ( C4::Context->preference('ILLOpacUnauthenticatedRequest') && !$patron ) {
$op = 'unauth_view';
my $sessionID = $query->cookie('CGISESSID');
my $session = C4::Auth::get_session($sessionID);
my $request_unblessed = $request->unblessed;
$request_unblessed->{updated} = $request_unblessed->{updated}->ymd;
$request_unblessed->{placed} = $request_unblessed->{placed}->ymd;
$request_unblessed->{unauthenticated_first_name} =
$request->extended_attributes->find( { 'type' => 'unauthenticated_first_name' } )->value;
$request_unblessed->{unauthenticated_last_name} =
$request->extended_attributes->find( { 'type' => 'unauthenticated_last_name' } )->value;
$request_unblessed->{unauthenticated_email} =
$request->extended_attributes->find( { 'type' => 'unauthenticated_email' } )->value;
$request_unblessed->{metadata} = $request->metadata;
my $capabilities = $request->capabilities;
$request_unblessed->{status} = $capabilities->{ $request->status }->{name};
$request_unblessed->{type} = $request->get_type;
$session->param(
'ill_request_unauthenticated',
uri_escape( encode_json($request_unblessed) )
);
$session->flush;
print $query->redirect('/cgi-bin/koha/opac-illrequests-unauthenticated.pl');
} else {
print $query->redirect('/cgi-bin/koha/opac-illrequests.pl?message=2');
exit;