reporter:label="RBDigital Digital Services Authorized">
<fields oils_persist:sequence="extra.rbdigital_digital_services_authorized_id_seq" oils_persist:primary="id">
<field reporter:label="Id" name="id" reporter:datatype="id" />
- <field reporter:label="Library Id" name="library_id" reporter:datatype="id" />
<field reporter:label="Home Library ID" name="home_ou" reporter:datatype="link" />
<field reporter:label="DS Id" name="digital_services_id" reporter:datatype="link" />
<field reporter:label="DS Library Id" name="digital_services_library_id" reporter:datatype="id" />
return $handler;
}
+sub logout_session {
+ my $self = shift;
+ my $conn = shift;
+ my $session_id = shift;
+ my $vendor = shift;
+ my $result = 0;
+ $logger->info("EbookAPI: logout_session: Clearing Session ($vendor) for session_id: $session_id");
+
+ try { # fail silently if there's no pre-existing cache to delete
+ $cache->delete_cache($session_id);
+ $result = 1;
+ } catch Error with {
+ $logger->info("EbookAPI: logout_session: No existing session found ($vendor) for session_id: $session_id");
+ };
+
+ $logger->info("EbookAPI: logout_session: Cache is cleared ($vendor) for session_id: $session_id");
+ my $cached_session = retrieve_session($session_id);
+
+ retrun $result;
+}
+
+__PACKAGE__->register_method(
+ method => 'logout_session',
+ api_name => 'open-ils.ebook_api.logout_session',
+ api_level => 1,
+ argc => 2,
+ signature => {
+ desc => "Logs out user from an existing EbookAPI session by clearing cache.",
+ params => [
+ {
+ name => 'session_id',
+ desc => 'The EbookAPI session ID being checked',
+ type => 'string'
+ },
+ {
+ name => 'vendor',
+ desc => 'The ebook vendor (e.g. "oneclickdigital")',
+ type => 'string'
+ }
+ ],
+ return => {
+ desc => 'Returns 1 for success and 0 failure',
+ type => 'number'
+ }
+ }
+);
sub check_session {
my $self = shift;
my $session_id = shift;
my $vendor = shift;
my $ou = shift;
-
+
+ $logger->info("EbookAPI: check_session: Checking Session ($vendor) for session_id (if any): $session_id");
return start_session($self, $conn, $vendor, $ou) unless $session_id;
+ # Check if the session requested belongs to the same vendor
+ if (index($session_id, $vendor) == -1) {
+ return start_session($self, $conn, $vendor, $ou);
+ }
+
my $cached_session = retrieve_session($session_id);
if ($cached_session) {
+ $logger->info("EbookAPI: check_session: Retrieving Cached Session ($vendor) for session_id: ".$session_id);
# re-authorize cached session, if applicable
my $handler = new_handler($session_id, $cached_session);
$handler->do_client_auth();
return;
}
} else {
+ $logger->info("EbookAPI: check_session: Creating New Session ($vendor)");
return start_session($self, $conn, $vendor, $ou);
}
}
+
__PACKAGE__->register_method(
method => 'check_session',
api_name => 'open-ils.ebook_api.check_session',
},
{
name => 'vendor',
- desc => 'The ebook vendor (e.g. "oneclickdigital")',
+ desc => 'The ebook vendor (e.g. "rbdigital")',
type => 'string'
},
{
);
sub _start_session {
+ my $authtoken = shift;
my $vendor = shift;
my $ou = shift;
+
$ou = $ou || 1; # default to top-level org unit
my $module;
-
+ $logger->info("EbookAPI: _start_session: New Session request received for $vendor.");
+
# determine EbookAPI handler from vendor name
# TODO handle API versions?
if ($vendor_handlers{$vendor}) {
$module = $vendor_handlers{$vendor};
+ $logger->info("EbookAPI: _start_session: Module '$module' ");
} else {
$logger->error("EbookAPI: No handler module found for $vendor!");
return;
}
- # TODO cache session? reuse an existing one if available?
-
# generate session ID
my ($sec, $usec) = gettimeofday();
my $r = rand();
- my $session_id = "ebook_api.ses." . md5_hex("$sec-$usec-$r");
+ my $session_id = "ebook_api.ses.$vendor." . md5_hex("$sec-$usec-$r");
my $args = {
vendor => $vendor,
$handler = $module->new($args); # create new handler object
$handler->initialize(); # set handler attributes
$handler->do_client_auth(); # authorize client session against API, if applicable
+
+ # Setup cache structure per vendor { authtoke => {'vendor' => {handler}} }
+ my $cache_value = {};
+ $cache_value->{$vendor} = $handler;
# our "session" is actually just our handler object, serialized and cached
- my $ckey = $handler->{session_id};
- $cache->put_cache($ckey, $handler, $cache_timeout);
+ $cache->put_cache($authtoken, $cache_value, $cache_timeout);
+
+ $logger->info("EbookAPI: _start_session: New session created (authtoken: $authtoken) for '$vendor' and ebook session_id: " .$handler->{session_id});
return $handler->{session_id};
}
sub start_session {
my $self = shift;
my $conn = shift;
+ my $authtoken = shift;
my $vendor = shift;
my $ou = shift;
- return _start_session($vendor, $ou);
+ return _start_session($authtoken, $vendor, $ou);
}
+
__PACKAGE__->register_method(
method => 'start_session',
api_name => 'open-ils.ebook_api.start_session',
$res = $handler->$action($title_id, $user_token);
}
-
if (defined ($res)) {
return $res;
} else {
sub _get_patron_xacts {
my ($xact_type, $auth, $session_id, $barcode) = @_;
- $logger->info("EbookAPI: getting $xact_type for patron $barcode");
+ $logger->info("EbookAPI: getting $xact_type for session_id: $session_id");
# verify that user is authenticated in EG
my $e = new_editor(authtoken => $auth);
return;
}
- my $handler = new_handler($session_id);
+ # Check if there is cached object before making calls to an API
+ $logger->info("EbookAPI: Calling cached session for ".$xact_type);
+ my $xact_value = _get_cache_value($session_id, $xact_type);
+
+ if (defined($xact_value)) {
+ return $xact_value;
+ }
+
+ my $handler = new_handler($session_id, retrieve_session($session_id));
my $user_token = _get_user_token($handler, $e, $barcode);
}
-# Call this method to retrieve the user token/patron id
+# Call this method to retrieve the user token/patron_id
sub _get_user_token {
my ($handler, $editor, $barcode) = @_;
-
+
#For RBDigital vendor, send user email || email
if (blessed($handler) eq 'OpenILS::Application::EbookAPI::RBDigital') {
- $logger->info("EbookAPI: handler->do_patron_auth(".$editor->requestor->usrname.", ".$editor->requestor->email.")");
- return $handler->do_patron_auth($editor->requestor->usrname, $editor->requestor->email);
+ my $cache_key = $editor->requestor->usrname.'_patron_id';
+
+ $logger->info("EbookAPI: _get_user_token cache key: $cache_key");
+ my $patron_id = _get_cache_value($handler->{session_id}, $cache_key);
+ if (defined($patron_id)) {
+ $logger->info("EbookAPI: Got cache key $cache_key from cache: $patron_id");
+ return $patron_id;
+ }
+
+ $logger->info("EbookAPI: session_id: ".$handler->{session_id}." handler->do_patron_auth(".$editor->requestor->usrname.", ".$editor->requestor->email.")");
+ $patron_id = $handler->do_patron_auth($editor->requestor->usrname, $editor->requestor->email);
+ # Add Patron id to cache
+ $handler->{$cache_key} = $patron_id;
+ # Overlay transactions onto existing cached handler.
+ update_cache($handler, 1);
+ return $patron_id;
}
$logger->info("EbookAPI: handler->do_patron_auth($barcode)");
} elsif ($self->api_name =~ /holds/) {
$xact_type = 'holds';
}
+
return _get_patron_xacts($xact_type, $auth, $session_id, $barcode);
}
+
__PACKAGE__->register_method(
method => 'get_patron_xacts',
api_name => 'open-ils.ebook_api.patron.get_checkouts',
# Get Patron ID from vendor
sub get_patron_id {
- my ($self, $conn, $auth, $session_id, $barcode) = @_;
- $logger->info("EbookAPI: getting patron id for patron $barcode");
+ my ($self, $conn, $auth, $session_id, $barcode) = @_;
+ my $patron_id = 0;
+
+ $logger->info("EbookAPI: getting patron id for patron $barcode");
# verify that user is authenticated in EG
my $editor = new_editor(authtoken => $auth);
$logger->error("EbookAPI: authentication failed: " . $editor->die_event);
return 0;
}
-
- $logger->error("EbookAPI: User Authenticated. Now, calling for patron authentication");
+
my $handler = new_handler($session_id);
return unless defined $handler;
- return $handler->do_patron_auth($editor->requestor->usrname, $editor->requestor->email);
+ return _get_user_token($handler, $editor, $barcode);
+}
+
+sub _get_cache_value {
+ my ($session_id, $key) = @_;
+ if (my $ses = $cache->get_cache($session_id)) {
+ $logger->info("EbookAPI: Got cached session for cache key: $key session: $session_id: " . Dumper($ses));
+ if (defined($ses->{$key})) {
+ $logger->info("EbookAPI: Returning cached session for ".$key);
+ return $ses->{$key};
+ }
+ }
+ return undef;
}
__PACKAGE__->register_method(
my ($self, $conn, $auth, $session_id, $isbn, $action) = @_;
$logger->info("EbookAPI: Processing wishlist (token: $auth, session_id: $session_id, action: $action) for $isbn");
-
+ my $cache_key = 'wishlist';
+
# verify that user is authenticated in EG
my $editor = new_editor(authtoken => $auth);
if (!$editor->checkauth) {
}
my $patron_id = _get_user_token($handler, $editor, 0);
+ if ($patron_id < 1) {
+ return;
+ }
if ($action eq 'add') {
- $logger->info("EbookAPI: Calling add_to_wishlist($patron_id, $isbn)");
+ $logger->debug("EbookAPI: Calling add_to_wishlist($patron_id, $isbn)");
return $handler->add_to_wishlist($patron_id, $isbn);
} elsif ($action eq 'delete') {
return $handler->delete_from_wishlist($patron_id, $isbn);
} elsif ($action eq 'get') {
- return $handler->get_wishlist($patron_id);
+ # Locate wishlist from cache first
+ my $wishlist = _get_cache_value($session_id, $cache_key);
+ if (defined($wishlist)) {
+ $logger->debug("EbookAPI: Got $cache_key from cache.");
+ return $wishlist;
+ }
+
+ $wishlist = $handler->get_wishlist($patron_id);
+
+ # Add Wishlist id to cache
+ $handler->{wishlist} = $wishlist;
+ # Overlay transactions onto existing cached handler.
+ update_cache($handler, 1);
+
+ return $wishlist;
}
$logger->error("EbookAPI: unsupported wishlist action requested");
$self->{base_uri} = $digital_services_req->content->[0]->api_url;
}
}
-
+
my $object_rdsa = _get_vendor_library($ou);
if ($object_rdsa) {
# This method will return the rbdigital library based on patron's home library id (usr.home_ou/org_unit.id)
sub _get_vendor_library {
- my $home_ou = @_;
+ my ($home_ou) = @_;
my $object_rdsa;
my $ebook_rdsa_req;
)->gather(1);
if ($ebook_rdsa_req && scalar (@$ebook_rdsa_req) > 0) {
- #read the library.id to find corresponding library id from digital services authorized table
$object_rdsa = $ebook_rdsa_req->[0];
}
if ($patron_id eq 0) {
# try to authenticate the user with a username
- $patron_id = $self-> _get_patron_id($username);
-
+ $patron_id = $self->_get_patron_id($username);
$logger->error("EbookAPI: Unable to get RBDigital Patron ID found for $username/$email");
}
return { message => "Vendor API error" };
}
-# DELETE //api.{domain}/v1/libraries/$library_id/patrons/$patrong_id/wishlist/$isbn
+# DELETE //api.{domain}/v1/libraries/$library_id/patrons/$patron_id/wishlist/$isbn
sub delete_from_wishlist {
my ($self, $patron_id, $isbn) = @_;
my $base_uri = $self->{base_uri};
use constant DEBUG_TIMING => 0;
+use constant {
+ COOKIE_EBOOK_RBDIGITAL => "rbdigital",
+ COOKIE_EBOOK_XACT_CACHE => "ebook_xact_cache",
+ COOKIE_EBOOK_TEST => "ebook_test"
+};
+
+my $ebook_rbdigital_session_id = '';
+
sub new {
my($class, $apache, $ctx) = @_;
# -----------------------------------------------------------------------------
sub load_common {
my $self = shift;
-
+
my $e = $self->editor;
my $ctx = $self->ctx;
-
+
# redirect non-https to https if we think we are already logged in
if ($self->cgi->cookie(COOKIE_LOGGEDIN)) {
return $self->redirect_ssl unless $self->cgi->https;
# Load vendor tabs for authenticated patrons only
if (defined($self->editor->requestor)) {
- # Call sub to get the session id
- my $session_id = _get_ebook_session_id();
+ $logger->info("EbookAPI: load_rbdigital_common: Token: ". $self->ctx->{authtoken});
+ my $session_id = "";
+ $logger->info("EbookAPI: load_rbdigital_common: COOKIE_EBOOK_RBDIGITAL: ".$self->cgi->cookie(COOKIE_EBOOK_RBDIGITAL));
+ if ($self->cgi->cookie(COOKIE_EBOOK_RBDIGITAL)) {
+ $session_id = $self->cgi->cookie(COOKIE_EBOOK_RBDIGITAL);
+ $logger->info("EbookAPI: load_rbdigital_common: previous session_id: $session_id");
+ }
+
+ $logger->info("EbookAPI: load_rbdigital_common: cookie value for rbdigital session: $session_id");
+ $session_id = _get_ebook_session_id($session_id, $self->editor->requestor->home_ou);
+ $ebook_rbdigital_session_id = $session_id;
+
+ $logger->info("EbookAPI: load_rbdigital_common: COOKIE_EBOOK_RBDIGITAL: ". $self->cgi->cookie(COOKIE_EBOOK_RBDIGITAL));
+
+ $logger->info("EbookAPI: load_rbdigital_common: after checking session id: $session_id");
+ $self->ctx->{rbdigital_session_id} = $session_id;
$self->ctx->{vendors} = [];
$self->ctx->{wishlist} = [];
$self->ctx->{vendor_library_url} = "";
} else {
$self->ctx->{rbdigital_patron_id} = 0;
+ $self->ctx->{rbdigital_session_id} = "";
$self->ctx->{vendors} = _get_default_vendor();
}
}
-secure => 0,
-value => '1',
-expires => $login_cookie_expires
+ ),
+ $cgi->cookie(
+ -name => COOKIE_EBOOK_RBDIGITAL,
+ -path => '/',
+ -secure => 0,
+ -value => $ebook_rbdigital_session_id,
+ -expires => $login_cookie_expires
)
];
);
} catch Error with {};
+ # Call method for an EBookAPI to clear session and logout the user
+ load_ebook_logout($self);
+
return $self->generic_redirect(
$redirect_to || $self->ctx->{home_page},
[
"http://www.galileo.usg.edu/express?pinesid=$token");
}
+# -----------------------------------------------------------------------------
+# Log out User from Ebook
+# -----------------------------------------------------------------------------
+sub load_ebook_logout {
+ my $self = shift;
+ my $session_id = $self->cgi->cookie(COOKIE_EBOOK_RBDIGITAL);
+ $logger->info("EbookAPI: load_ebook_logout: started to clear session $session_id");
+
+ # First, delete ebook cookies
+ $self->cgi->cookie(
+ -name => COOKIE_EBOOK_RBDIGITAL,
+ -path => '/',
+ -value => '',
+ -expires => '-1h'
+ );
+
+ $self->cgi->cookie(
+ -name => COOKIE_EBOOK_XACT_CACHE,
+ -path => '/',
+ -value => '',
+ -expires => '-1h'
+ );
+
+ $self->cgi->cookie(
+ -name => COOKIE_EBOOK_TEST,
+ -path => '/',
+ -value => '',
+ -expires => '-1h'
+ );
+
+ # Second, clear cache
+ # Call sub to retrieve new/existing session id
+ if(defined($session_id)) {
+ $logger->info("EbookAPI: load_ebook_logout: calling logout to clear session: $session_id");
+ _logout_session($session_id);
+ }
+
+}
1;
use IO::Select;
my $U = 'OpenILS::Application::AppUtils';
+use constant COOKIE_EBOOK_RBDIGITAL => 'rbdigital';
+
our $ac_types = ['toc', 'anotes', 'excerpt', 'summary', 'reviews'];
# context additions:
unless $isbn and $isbn =~ /^\d+$/;
# Call sub to get the session id
- my $session_id = _get_ebook_session_id();
+ my $session_id = _get_ebook_session_id($self->cgi->cookie(COOKIE_EBOOK_RBDIGITAL), $self->editor->requestor->home_ou);
$ctx->{title_info} = _get_ebook_title_info($session_id, $isbn);
my $page_size = 10;
$ctx->{recommended_books} = _get_book_recommendations($self->editor->authtoken, $session_id, $isbn, $media_format, $page_index, $page_size);
}
-
+
#Get Patron Wishlist
# Return hash reference of wishlist {isbn => true}
$ctx->{wishlist_map} = _get_patron_wishlist_isbn_map($self->editor->authtoken, $session_id);
$Data::Dumper::Indent = 0;
my $U = 'OpenILS::Application::AppUtils';
+use constant COOKIE_EBOOK_RBDIGITAL => 'rbdigital';
+
use constant EBOOK_API_VENDOR => 'rbdigital';
use constant EBOOK_API_OU => 1;
$logger->info('EbookAPI: RBDigitalSearch calling an API to get search filters');
# Call sub to get the session id
- my $session_id = _get_ebook_session_id();
+ my $session_id = _get_ebook_session_id($self->cgi->cookie(COOKIE_EBOOK_RBDIGITAL),$self->editor->requestor->home_ou);
my $ebook_api = OpenSRF::AppSession->create('open-ils.ebook_api');
my $api_request = $ebook_api->request('open-ils.ebook_api.get_search_filters', $self->editor->authtoken, $session_id);
$logger->info('EbookAPI: RBDigitalSearch calling an API to search fields for mapping with evergreen');
# Call sub to get the session id
- my $session_id = _get_ebook_session_id();
+ my $session_id = _get_ebook_session_id($self->cgi->cookie(COOKIE_EBOOK_RBDIGITAL),$self->editor->requestor->home_ou);
my $ebook_api = OpenSRF::AppSession->create('open-ils.ebook_api');
my $api_request = $ebook_api->request('open-ils.ebook_api.get_search_filters', $self->editor->authtoken, $session_id);
$logger->info('EbookAPI: RBDigitalSearch User is authenticated.');
# Call sub to get the session id
- $session_id = _get_ebook_session_id();
+ $session_id = _get_ebook_session_id($self->cgi->cookie(COOKIE_EBOOK_RBDIGITAL),$self->editor->requestor->home_ou);
# Read all the parameters passed
my $auth_session = $cgi->cookie('ses') || $cgi->param('ses');
if ($cgi->param('qtype') && $is_eg_advanced_search == 1) {
#Evergreen Advanced Search:
@search_inputs = _parse_evergreen_advanced_search($cgi);
- $logger->info("Parsed User Query: ".Dumper(@search_inputs));
+ $logger->debug("Parsed User Query: ".Dumper(@search_inputs));
$value_to_search = '';
} else {
#RBDigital Advanced Search:
if (defined($checkouts_req->content)) {
$logger->info('EbookAPI: RBDigitalSearch Patron Checkouts API call was successful');
# Loop over the checkout contents and build hash array for easier to use in the UI: { isbn => '1', ...}
- $logger->info("Checkout response: " . Dumper($checkouts_req->content));
+ $logger->debug("Checkout response: " . Dumper($checkouts_req->content));
foreach my $value (@{$checkouts_req->content}) {
$checkouts_ref{$value->{title_id}} = $value->{download_url};
}
if (my $resp = $api_request->recv) {
return $resp->content;
}
-
+
return 0;
}
sub _get_ebook_session_id {
+ my ($session_id, $home_ou) = @_;
+ $logger->info("EbookAPI: _get_ebook_session_id home library: $home_ou ");
+
# Create an instance of EbookAPI
my $ebook_api = OpenSRF::AppSession->create('open-ils.ebook_api');
my $session_id_req = $ebook_api->request(
- 'open-ils.ebook_api.start_session', EBOOK_API_VENDOR, EBOOK_API_OU);
- my $session_id = $session_id_req->recv->content;
+ 'open-ils.ebook_api.check_session', $session_id, EBOOK_API_VENDOR, $home_ou);
+ $session_id = $session_id_req->recv->content;
return $session_id;
}
+sub _logout_session {
+ my ($session_id) = @_;
+ $logger->debug("EbookAPI: _logout_session Logging user out from session_id: $session_id ");
+ # Create an instance of EbookAPI
+ my $ebook_api = OpenSRF::AppSession->create('open-ils.ebook_api');
+ my $logout_req = $ebook_api->request(
+ 'open-ils.ebook_api.logout_session', $session_id, EBOOK_API_VENDOR);
+}
+
sub _search {
my ($authtoken, $session_id, $is_eg_advanced_search,
$value_to_search, $search_type,
$logger->error('EbookAPI: RBDigitalSearch Basic Search API call failed');
return Apache2::Const::OK;
}
-
- #$self->timelog("Returned from the basic search from RBDigital library");
- $logger->info('EbookAPI: RBDigitalSearch Done calling search API');
+
+ $logger->debug('EbookAPI: RBDigitalSearch Done calling search API');
} catch Error with {
my $err = shift;
<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/opac/ebook_api/session.js[% ctx.cache_key %]"></script>
<script type="text/javascript" src="[% ctx.media_prefix %]/js/ui/default/opac/ebook_api/ebook.js[% ctx.cache_key %]"></script>
<script type="text/javascript">
+[% #Add Ebook sessions into placeholders %]
+var ebook_sessions = {};
+ebook_sessions.rbdigital_session_id = "[% ctx.rbdigital_session_id; %]";
// translatable strings as JS variables
var l_strings = {};
dojo.addOnLoad(function() {
var logout_handle = dojo.connect(dojo.byId('#logout_link'), 'onclick', function() {
dojo.forEach(cookie_registry, function(cookie) {
+ console.log('Clearing Cookie: '+cookie);
dojo.cookie(cookie, '', {path: '/', expires: '-1h'});
});
// When we switch to jQuery, use .one()
default_search_link.attr("href",default_search_uri+ query_string);
}
}
-
});
function setupEventHandlers() {
if (typeof localStorage[key] != 'undefined' ) {
return JSON.parse(localStorage[key]);
}
+
+ return "";
}
\ No newline at end of file
var resp = r.recv();
if (resp) {
var ses = resp.content();
- dojo.cookie(vendor, ses, {path: '/'});
+ dojo.cookie(vendor, ses,{path: '/'});
+ ebook_sessions.rbdigital_session_id = ses;
return callback(vendor,ses);
}
}
// (check_session method will fallback to start_session if no session ID is provided)
function checkSession(vendor, callback) {
var ses = dojo.cookie(vendor) || null;
- if (ses == null)
- return startSession(vendor,callback);
+ //Check session inside js variable defined in base_js.tt2
+ if (ses == null) {
+ ses = ebook_sessions.rbdigital_session_id;
+ //Check if session is empty here as well
+ if (ses == null) {
+ return startSession(vendor,callback);
+ } else {
+ dojo.cookie(vendor, ses, {path: '/'});
+ }
+ }
+
console.log('checking ebook API session for ' + vendor);
new OpenSRF.ClientSession('open-ils.ebook_api').request({
method: 'open-ils.ebook_api.check_session',
if (resp) {
var new_ses = resp.content();
dojo.cookie(vendor, new_ses, {path: '/'});
+ ebook_sessions.rbdigital_session_id = new_ses;
return callback(vendor,new_ses);
}
}