From: Thomas Berezansky Date: Mon, 21 Nov 2011 21:51:50 +0000 (-0500) Subject: Call set_audit_info and clear_audit_info DB funcs X-Git-Tag: sprint4-merge-nov22~4460 X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=db327a6c66de2efaf1aaebbe2f0220fa65cf317f;p=working%2FEvergreen.git Call set_audit_info and clear_audit_info DB funcs Set whenever we can (including automatically via pcrud) Clear whenever we disconnect (hopefully) from a location we set from. Signed-off-by: Thomas Berezansky Signed-off-by: Jason Stephenson Signed-off-by: Mike Rylander --- diff --git a/Open-ILS/include/openils/oils_sql.h b/Open-ILS/include/openils/oils_sql.h index 6674d213c7..d581c4b06c 100644 --- a/Open-ILS/include/openils/oils_sql.h +++ b/Open-ILS/include/openils/oils_sql.h @@ -56,6 +56,8 @@ int doIdList( osrfMethodContext* ctx ); int is_identifier( const char* s); int is_good_operator( const char* op ); +int setAuditInfo( osrfMethodContext* ctx ); + #ifdef __cplusplus } #endif diff --git a/Open-ILS/src/c-apps/oils_cstore.c b/Open-ILS/src/c-apps/oils_cstore.c index a2aa3fac73..5014605f1e 100644 --- a/Open-ILS/src/c-apps/oils_cstore.c +++ b/Open-ILS/src/c-apps/oils_cstore.c @@ -69,6 +69,7 @@ void osrfAppChildExit( void ) { - savepoint.set - savepoint.release - savepoint.rollback + - set_audit_info For each non-virtual class, create up to eight class-specific methods: @@ -165,6 +166,12 @@ int osrfAppInitialize( void ) { osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR(method_name), "rollbackSavepoint", "", 1, 0 ); + buffer_reset(method_name); + OSRF_BUFFER_ADD(method_name, modulename ); + OSRF_BUFFER_ADD(method_name, ".set_audit_info"); + osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR(method_name), + "setAuditInfo", "", 3, 0 ); + static const char* global_method[] = { "create", "retrieve", diff --git a/Open-ILS/src/c-apps/oils_pcrud.c b/Open-ILS/src/c-apps/oils_pcrud.c index b95bdae1b9..18fadfc593 100644 --- a/Open-ILS/src/c-apps/oils_pcrud.c +++ b/Open-ILS/src/c-apps/oils_pcrud.c @@ -72,6 +72,7 @@ void osrfAppChildExit( void ) { - savepoint.set - savepoint.release - savepoint.rollback + - set_audit_info For each non-virtual class, create up to eight class-specific methods: @@ -160,6 +161,12 @@ int osrfAppInitialize( void ) { osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR(method_name), "rollbackSavepoint", "", 1, 0 ); + buffer_reset(method_name); + OSRF_BUFFER_ADD(method_name, modulename ); + OSRF_BUFFER_ADD(method_name, ".set_audit_info"); + osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR(method_name), + "setAuditInfo", "", 3, 0 ); + static const char* global_method[] = { "create", "retrieve", diff --git a/Open-ILS/src/c-apps/oils_rstore.c b/Open-ILS/src/c-apps/oils_rstore.c index ae76a7608c..d503ce10f6 100644 --- a/Open-ILS/src/c-apps/oils_rstore.c +++ b/Open-ILS/src/c-apps/oils_rstore.c @@ -69,6 +69,7 @@ void osrfAppChildExit( void ) { - savepoint.set - savepoint.release - savepoint.rollback + - set_audit_info For each non-virtual class, create up to eight class-specific methods: @@ -164,6 +165,12 @@ int osrfAppInitialize( void ) { osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR(method_name), "rollbackSavepoint", "", 1, 0 ); + buffer_reset(method_name); + OSRF_BUFFER_ADD(method_name, modulename ); + OSRF_BUFFER_ADD(method_name, ".set_audit_info"); + osrfAppRegisterMethod( modulename, OSRF_BUFFER_C_STR(method_name), + "setAuditInfo", "", 3, 0 ); + static const char* global_method[] = { "create", "retrieve", diff --git a/Open-ILS/src/c-apps/oils_sql.c b/Open-ILS/src/c-apps/oils_sql.c index 29d80d5a17..887a2df89e 100644 --- a/Open-ILS/src/c-apps/oils_sql.c +++ b/Open-ILS/src/c-apps/oils_sql.c @@ -143,6 +143,8 @@ static int perm_at_threshold = 5; static int enforce_pcrud = 0; // Boolean static char* modulename = NULL; +int writeAuditInfo( osrfMethodContext* ctx, const char* user_id, const char* ws_id); + /** @brief Connect to the database. @return A database connection if successful, or NULL if not. @@ -473,6 +475,14 @@ void userDataFree( void* blob ) { errnum, msg ? msg : "(No description available)" ); }; } + if( writehandle ) { + if( !dbi_conn_query( writehandle, "SELECT auditor.clear_audit_info();" ) ) { + const char* msg; + int errnum = dbi_conn_error( writehandle, &msg ); + osrfLogWarning( OSRF_LOG_MARK, "Unable to perform audit info clearing: %d %s", + errnum, msg ? msg : "(No description available)" ); + } + } osrfHashFree( hash ); } @@ -1408,6 +1418,10 @@ static const jsonObject* verifyUserPCRUD( osrfMethodContext* ctx ) { free( m ); jsonObjectFree( user ); user = NULL; + } else if( writeAuditInfo( ctx, oilsFMGetStringConst( user, "id" ), oilsFMGetStringConst( user, "wsid" ) ) ) { + // Failed to set audit information - But note that write_audit_info already set error information. + jsonObjectFree( user ); + user = NULL; } setUserLogin( ctx, user ); @@ -7140,4 +7154,87 @@ static void clear_query_stack( void ) { pop_query_frame(); } +/** + @brief Implement the set_audit_info method. + @param ctx Pointer to the method context. + @return Zero if successful, or -1 if not. + + Issue a SAVEPOINT to the database server. + + Method parameters: + - authkey + - user id (int) + - workstation id (int) + + If user id is not provided the authkey will be used. + For PCRUD the authkey is always used, even if a user is provided. +*/ +int setAuditInfo( osrfMethodContext* ctx ) { + if(osrfMethodVerifyContext( ctx )) { + osrfLogError( OSRF_LOG_MARK, "Invalid method context" ); + return -1; + } + + // Get the user id from the parameters + const char* user_id = jsonObjectGetString( jsonObjectGetIndex(ctx->params, 1) ); + + if( enforce_pcrud || !user_id ) { + timeout_needs_resetting = 1; + const jsonObject* user = verifyUserPCRUD( ctx ); + if( !user ) + return -1; + osrfAppRespondComplete( ctx, NULL ); + return 0; + } + + // Not PCRUD and have a user_id? + int result = writeAuditInfo( ctx, user_id, jsonObjectGetString( jsonObjectGetIndex(ctx->params, 2) ) ); + osrfAppRespondComplete( ctx, NULL ); + return result; +} + +/** + @brief Save a audit info + @param ctx Pointer to the method context. + @param user_id User ID to write as a string + @param ws_id Workstation ID to write as a string +*/ +int writeAuditInfo( osrfMethodContext* ctx, const char* user_id, const char* ws_id) { + if( ctx && ctx->session ) { + osrfAppSession* session = ctx->session; + + osrfHash* cache = session->userData; + + // If the session doesn't already have a hash, create one. Make sure + // that the application session frees the hash when it terminates. + if( NULL == cache ) { + session->userData = cache = osrfNewHash(); + osrfHashSetCallback( cache, &sessionDataFree ); + ctx->session->userDataFree = &userDataFree; + } + + dbi_result result = dbi_conn_queryf( writehandle, "SELECT auditor.set_audit_info( %s, %s );", user_id, ws_id ? ws_id : "NULL" ); + if( !result ) { + osrfLogWarning( OSRF_LOG_MARK, "BAD RESULT" ); + const char* msg; + int errnum = dbi_conn_error( writehandle, &msg ); + osrfLogError( + OSRF_LOG_MARK, + "%s: Error setting auditor information: %d %s", + modulename, + errnum, + msg ? msg : "(No description available)" + ); + osrfAppSessionStatus( ctx->session, OSRF_STATUS_INTERNALSERVERERROR, + "osrfMethodException", ctx->request, "Error setting auditor info" ); + if( !oilsIsDBConnected( writehandle )) + osrfAppSessionPanic( ctx->session ); + return -1; + } else { + dbi_result_free( result ); + return 0; + } + } +} + /*@}*/ diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm index 1599d30128..4ba9ad5f0a 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Actor.pm @@ -351,6 +351,7 @@ sub update_patron { $evt = check_group_perm($session, $user_obj, $patron); return $evt if $evt; + $apputils->set_audit_info($session, $user_session, $user_obj->id, $user_obj->wsid); # $new_patron is the patron in progress. $patron is the original patron # passed in with the method. new_patron will change as the components @@ -1037,6 +1038,7 @@ sub set_user_work_ous { return $evt if $evt; my $session = $apputils->start_db_session(); + $apputils->set_audit_info($session, $ses, $requestor->id, $requestor->wsid); for my $map (@$maps) { @@ -1077,6 +1079,7 @@ sub set_user_perms { my( $user_obj, $evt ) = $U->checkses($ses); return $evt if $evt; + $apputils->set_audit_info($session, $ses, $user_obj->id, $user_obj->wsid); my $perms = $session->request('open-ils.storage.permission.user_perms.atomic', $user_obj->id)->gather(1); diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/AppUtils.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/AppUtils.pm index e8369ea9a9..07bd151db3 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/AppUtils.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/AppUtils.pm @@ -45,6 +45,18 @@ sub start_db_session { return $session; } +sub set_audit_info { + my $self = shift; + my $session = shift; + my $authtoken = shift; + my $user_id = shift; + my $ws_id = shift; + + my $audit_req = $session->request( "open-ils.storage.set_audit_info", $authtoken, $user_id, $ws_id ); + my $audit_resp = $audit_req->recv(); + $audit_req->finish(); +} + my $PERM_QUERY = { select => { au => [ { diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Money.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Money.pm index 1058e8c342..d4008538a5 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Money.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Money.pm @@ -586,6 +586,7 @@ sub create_grocery_bill { $transaction->clear_id; my $session = $apputils->start_db_session; + $apputils->set_audit_info($login, $staff->id, $staff->wsid); my $transid = $session->request( 'open-ils.storage.direct.money.grocery.create', $transaction)->gather(1); diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/StatCat.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/StatCat.pm index 8ca8325755..aadb8c76b0 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/StatCat.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/StatCat.pm @@ -177,6 +177,7 @@ sub stat_cat_create { my $session = $apputils->start_db_session(); + $apputils->set_audit_info($user_session, $user_obj->id, $user_obj->wsid); my $newid = _create_stat_cat($session, $stat_cat, $method); if( ref($stat_cat->entries) ) { @@ -296,6 +297,7 @@ sub update_stat_entry { return $evt if $evt; my $session = $apputils->start_db_session(); + $apputils->set_audit_info($user_session, $user_obj->id, $user_obj->wsid); my $req = $session->request($method, $entry); my $status = $req->gather(1); $apputils->commit_db_session($session); @@ -328,6 +330,7 @@ sub update_stat { return $evt if $evt; my $session = $apputils->start_db_session(); + $apputils->set_audit_info($user_session, $user_obj->id, $user_obj->wsid); my $req = $session->request($method, $cat); my $status = $req->gather(1); $apputils->commit_db_session($session); @@ -361,6 +364,7 @@ sub create_stat_entry { $entry->clear_id(); my $session = $apputils->start_db_session(); + $apputils->set_audit_info($user_session, $user_obj->id, $user_obj->wsid); my $req = $session->request($method, $entry); my $status = $req->gather(1); $apputils->commit_db_session($session); @@ -416,6 +420,7 @@ sub create_stat_map { $map->clear_id(); my $session = $apputils->start_db_session(); + $apputils->set_audit_info($user_session, $user_obj->id, $user_obj->wsid); my $req = $session->request($method, $map); my $newid = $req->gather(1); warn "Created new stat cat map with id $newid\n"; @@ -466,6 +471,7 @@ sub update_stat_map { my $session = $apputils->start_db_session(); + $apputils->set_audit_info($user_session, $user_obj->id, $user_obj->wsid); my $req = $session->request($method, $map); my $newid = $req->gather(1); warn "Updated new stat cat map with id $newid\n"; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Survey.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Survey.pm index 9f75be3ddf..98f046f2fa 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Survey.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Survey.pm @@ -38,6 +38,7 @@ sub add_survey { return $evt if $evt; my $session = $apputils->start_db_session(); + $apputils->set_audit_info($user_session, $user_obj->id, $user_obj->wsid); my $err = undef; my $id; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Transit.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Transit.pm index ff4796e97d..e0900dcd32 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Transit.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Circ/Transit.pm @@ -44,6 +44,7 @@ sub copy_transit_receive { ($copy, $evt) = $U->fetch_copy_by_barcode($params{barcode}) unless $copy; return $evt if $evt; my $session = $U->start_db_session(); + $U->set_audit_info($authtoken, $requestor->id, $requestor->wsid); $evt = transit_receive( $self, $copy, $requestor, $session ); $U->commit_db_session($session) if $U->event_equals($evt,'SUCCESS'); return $evt; @@ -133,6 +134,7 @@ sub copy_transit_create { my $source = $requestor->home_ou; my $dest = $params{destination} || $copy->circ_lib; my $transit = Fieldmapper::action::transit_copy->new; + $U->set_audit_info($authtoken, $requestor->id, $requestor->wsid); $logger->activity("User ". $requestor->id ." creating a ". " new copy transit for copy ".$copy->id." to org $dest"); diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Driver/Pg.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Driver/Pg.pm index 8fd85155d3..95d9db4127 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Driver/Pg.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Driver/Pg.pm @@ -145,6 +145,7 @@ # } my $_xact_session; + my $_audit_session; sub current_xact_session { my $self = shift; @@ -154,6 +155,14 @@ return undef; } + sub current_audit_session { + my $self = shift; + if (defined($_audit_session)) { + return $_audit_session; + } + return undef; + } + sub current_xact_is_auto { my $self = shift; my $auto = shift; @@ -183,6 +192,16 @@ return $_xact_session; } + sub set_audit_session { + my $self = shift; + my $ses = shift; + if (!defined($ses)) { + return undef; + } + $_audit_session = $ses; + return $_audit_session; + } + sub unset_xact_session { my $self = shift; my $ses = $_xact_session; @@ -190,6 +209,13 @@ return $ses; } + sub unset_audit_session { + my $self = shift; + my $ses = $_audit_session; + undef $_audit_session; + return $ses; + } + } 1; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Driver/Pg/storage.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Driver/Pg/storage.pm index d7623d0d18..989d84cfd5 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Driver/Pg/storage.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Storage/Driver/Pg/storage.pm @@ -222,6 +222,84 @@ argc => 1, ); + sub pg_set_audit_info { + my $self = shift; + my $client = shift; + my $authtoken = shift; + my $user_id = shift; + my $ws_id = shift; + + local $OpenILS::Application::Storage::WRITE = 1; + + $log->debug("Setting auditor information", INFO); + + if($pg->current_audit_session) { + $log->debug("Already sent audit data.", INFO); + return 1; + } + + my $dbh = OpenILS::Application::Storage::CDBI->db_Main; + + try { + if(!$user_id) { + my $ses = OpenSRF::AppSession->create('open-ils.auth'); + my $content = $ses->request('open-ils.auth.session.retrieve', $authtoken, 1)->gather(1); + if(!$content or !$content->{userObj}) { + return 0; + } + $user_id = $content->{userObj}->id; + $ws_id = $content->{userObj}->wsid; + } + $ws_id = 'NULL' unless $ws_id; + $dbh->do("SELECT auditor.set_audit_info($user_id, $ws_id);"); + } catch Error with { + my $e = shift; + $log->debug("Failed to set auditor information: ".$e, INFO); + throw $e; + }; + + $pg->set_audit_session( $client->session ); + + my $death_cb = $client->session->register_callback( + death => sub { + __PACKAGE__->pg_clear_audit_info; + } + ); + + $log->debug("Registered 'death' callback [$death_cb] for clearing audit information", DEBUG); + + $client->session->session_data( death_cb_ai => $death_cb ); + + return 1; + + } + __PACKAGE__->register_method( + method => 'pg_set_audit_info', + api_name => 'open-ils.storage.set_audit_info', + api_level => 1, + argc => 3, + ); + + sub pg_clear_audit_info { + my $self = shift; + + try { + my $dbh = OpenILS::Application::Storage::CDBI->db_Main; + $log->debug("Clearing Audit Information", INFO); + $dbh->do("SELECT auditor.clear_audit_info();"); + } catch Error with { + my $e = shift; + $log->debug("Failed to clear audit information: ".$e, INFO); + }; + + $pg->current_audit_session->unregister_callback( death => + $pg->current_audit_session->session_data( 'death_cb_ai' ) + ) if ($pg->current_audit_session); + + $pg->unset_audit_session; + } + + sub copy_create_start { my $self = shift; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/CStoreEditor.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/CStoreEditor.pm index 18e1775284..d41e435e26 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Utils/CStoreEditor.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Utils/CStoreEditor.pm @@ -237,6 +237,18 @@ sub xact_begin { my $stat = $self->request($self->app . '.transaction.begin'); $self->log(E, "error starting database transaction") unless $stat; $self->{xact_id} = $stat; + if($self->authtoken) { + if(!$self->requestor) { + $self->checkauth; + } + my $user_id = undef; + my $ws_id = undef; + if($self->requestor) { + $user_id = $self->requestor->id; + $ws_id = $self->requestor->wsid; + } + $self->request($self->app . '.set_audit_info', $self->authtoken, $user_id, $ws_id); + } } $self->{xact} = 1; return $self->{xact_id}; diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Utils/Editor.pm b/Open-ILS/src/perlmods/lib/OpenILS/Utils/Editor.pm index 801faff550..e31e29d9d1 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Utils/Editor.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Utils/Editor.pm @@ -135,6 +135,18 @@ sub xact_start { $self->log(D, "starting new db session"); my $stat = $self->request('open-ils.storage.transaction.begin'); $self->log(E, "error starting database transaction") unless $stat; + if($self->authtoken) { + if(!$self->requestor) { + $self->checkauth; + } + my $user_id = undef; + my $ws_id = undef; + if($self->requestor) { + $user_id = $self->requestor->id; + $ws_id = $self->requestor->wsid; + } + $self->request('open-ils.storage.set_audit_info', $self->authtoken, $user_id, $ws_id); + } return $stat; } diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/BadDebt.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/BadDebt.pm index 72cce27a94..007623daeb 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/BadDebt.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/BadDebt.pm @@ -89,6 +89,7 @@ sub handler { $cstore->connect(); $cstore->request('open-ils.cstore.transaction.begin')->gather(1); + $cstore->request('open-ils.cstore.set_audit_info', $auth_ses, $user->id, $user->wsid)->gather(1); for my $xact ( @xacts ) { try { diff --git a/Open-ILS/src/perlmods/lib/OpenILS/WWW/TemplateBatchBibUpdate.pm b/Open-ILS/src/perlmods/lib/OpenILS/WWW/TemplateBatchBibUpdate.pm index 56af440465..f72ac17f90 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/WWW/TemplateBatchBibUpdate.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/WWW/TemplateBatchBibUpdate.pm @@ -89,6 +89,7 @@ sub handler { my $e = OpenSRF::AppSession->connect('open-ils.cstore'); $e->request('open-ils.cstore.transaction.begin')->gather(1); + $e->request('open-ils.cstore.set_audit_info', $authid, $usr->id, $usr->wsid)->gather(1); # still no records ... my $container = $cgi->param('containerid');