From c6938328c08c98fc6bc0c58a7ebd770fd74b7e15 Mon Sep 17 00:00:00 2001 From: Galen Charlton Date: Tue, 23 Feb 2016 12:09:15 -0500 Subject: [PATCH] LP#1485374: add way for C code to make TZ-aware subrequests This patch adds a helper routine to allow C methods to make subrequests that pass the client time zone along. This helper is in turn used during authentication to ensure that the user object that is returned has timestamps that are in the time zone of the client that makes the original authentication request. Signed-off-by: Galen Charlton Signed-off-by: Mike Rylander Conflicts: Open-ILS/src/c-apps/oils_auth.c --- Open-ILS/include/openils/oils_utils.h | 12 ++++-- Open-ILS/src/c-apps/oils_auth.c | 19 +++++---- Open-ILS/src/c-apps/oils_auth_internal.c | 12 +++--- Open-ILS/src/c-apps/oils_utils.c | 72 ++++++++++++++++++++++++++++---- Open-ILS/src/extras/oils_requestor.c | 5 +++ 5 files changed, 94 insertions(+), 26 deletions(-) diff --git a/Open-ILS/include/openils/oils_utils.h b/Open-ILS/include/openils/oils_utils.h index 6b391f2323..839c582642 100644 --- a/Open-ILS/include/openils/oils_utils.h +++ b/Open-ILS/include/openils/oils_utils.h @@ -13,6 +13,7 @@ #include "oils_constants.h" #include "opensrf/osrf_app_session.h" #include "opensrf/osrf_settings.h" +#include "opensrf/osrf_application.h" #ifdef __cplusplus extern "C" { @@ -65,15 +66,20 @@ oilsEvent* oilsUtilsCheckPerms( int userid, int orgid, char* permissions[], int jsonObject* oilsUtilsQuickReq( const char* service, const char* method, const jsonObject* params ); +jsonObject* oilsUtilsQuickReqCtx( osrfMethodContext* ctx, const char* service, + const char* method, const jsonObject* params ); + jsonObject* oilsUtilsStorageReq( const char* method, const jsonObject* params ); +jsonObject* oilsUtilsStorageReqCtx( osrfMethodContext* ctx, const char* method, const jsonObject* params ); jsonObject* oilsUtilsCStoreReq( const char* method, const jsonObject* params ); +jsonObject* oilsUtilsCStoreReqCtx( osrfMethodContext* ctx, const char* method, const jsonObject* params ); /** * Searches the storage server for a user with the given username * Caller is responsible for freeing the returned object */ -jsonObject* oilsUtilsFetchUserByUsername( const char* name ); +jsonObject* oilsUtilsFetchUserByUsername( osrfMethodContext* ctx, const char* name ); /** @@ -95,7 +101,7 @@ char* oilsUtilsLogin( const char* uname, const char* passwd, const char* type, i */ jsonObject* oilsUtilsFetchWorkstation( long id ); -jsonObject* oilsUtilsFetchUserByBarcode(const char* barcode); +jsonObject* oilsUtilsFetchUserByBarcode(osrfMethodContext* ctx, const char* barcode); jsonObject* oilsUtilsFetchWorkstationByName( const char* name ); @@ -108,7 +114,7 @@ long oilsUtilsIntervalToSeconds( const char* interval ); * Creates actor.usr_activity entries * @return The number of rows created. 0 or 1. */ -int oilsUtilsTrackUserActivity( long usr, const char* ewho, const char* ewhat, const char* ehow ); +int oilsUtilsTrackUserActivity( osrfMethodContext* ctx, long usr, const char* ewho, const char* ewhat, const char* ehow ); /** * Returns the ID of the root org unit (parent_ou = NULL) diff --git a/Open-ILS/src/c-apps/oils_auth.c b/Open-ILS/src/c-apps/oils_auth.c index 068e0f19c4..628efc88ec 100644 --- a/Open-ILS/src/c-apps/oils_auth.c +++ b/Open-ILS/src/c-apps/oils_auth.c @@ -239,7 +239,7 @@ static int oilsAuthInitUsernameHandler( int user_id = -1; jsonObject* resp = NULL; // free - jsonObject* user_obj = oilsUtilsFetchUserByUsername(username); // free + jsonObject* user_obj = oilsUtilsFetchUserByUsername(ctx, username); // free if (user_obj && user_obj->type != JSON_NULL) user_id = oilsFMGetObjectId(user_obj); @@ -281,7 +281,7 @@ static int oilsAuthInitBarcodeHandler( int user_id = -1; jsonObject* resp = NULL; // free - jsonObject* user_obj = oilsUtilsFetchUserByBarcode(barcode); // free + jsonObject* user_obj = oilsUtilsFetchUserByBarcode(ctx, barcode); // free if (user_obj && user_obj->type != JSON_NULL) user_id = oilsFMGetObjectId(user_obj); @@ -490,7 +490,7 @@ static int oilsAuthVerifyPassword( const osrfMethodContext* ctx, int user_id, Returns the event that should be returned to the user. Event must be freed */ -static oilsEvent* oilsAuthHandleLoginOK( jsonObject* userObj, const char* uname, +static oilsEvent* oilsAuthHandleLoginOK( osrfMethodContext* ctx, jsonObject* userObj, const char* uname, const char* type, int orgloc, const char* workstation ) { oilsEvent* response = NULL; @@ -503,7 +503,8 @@ static oilsEvent* oilsAuthHandleLoginOK( jsonObject* userObj, const char* uname, if (workstation) jsonObjectSetKey(params, "workstation", jsonNewObject(workstation)); - jsonObject* authEvt = oilsUtilsQuickReq( + jsonObject* authEvt = oilsUtilsQuickReqCtx( + ctx, "open-ils.auth_internal", "open-ils.auth_internal.session.create", params); jsonObjectFree(params); @@ -644,8 +645,8 @@ int oilsAuthComplete( osrfMethodContext* ctx ) { } jsonObject* param = jsonNewNumberObject(user_id); // free - userObj = oilsUtilsCStoreReq( - "open-ils.cstore.direct.actor.user.retrieve", param); + userObj = oilsUtilsCStoreReqCtx( + ctx, "open-ils.cstore.direct.actor.user.retrieve", param); jsonObjectFree(param); char* freeable_uname = NULL; @@ -662,7 +663,8 @@ int oilsAuthComplete( osrfMethodContext* ctx ) { jsonObjectSetKey(params, "login_type", jsonNewObject(type)); if (barcode) jsonObjectSetKey(params, "barcode", jsonNewObject(barcode)); - jsonObject* authEvt = oilsUtilsQuickReq( // freed after password test + jsonObject* authEvt = oilsUtilsQuickReqCtx( // freed after password test + ctx "open-ils.auth_internal", "open-ils.auth_internal.user.validate", params); jsonObjectFree(params); @@ -743,10 +745,11 @@ int oilsAuthComplete( osrfMethodContext* ctx ) { } else { response = oilsAuthHandleLoginOK( - userObj, uname, type, orgloc, workstation); + ctx, userObj, uname, type, orgloc, workstation); } oilsUtilsTrackUserActivity( + ctx, oilsFMGetObjectId(userObj), ewho, ewhat, osrfAppSessionGetIngress() diff --git a/Open-ILS/src/c-apps/oils_auth_internal.c b/Open-ILS/src/c-apps/oils_auth_internal.c index a2fa08ee19..96ad19335f 100644 --- a/Open-ILS/src/c-apps/oils_auth_internal.c +++ b/Open-ILS/src/c-apps/oils_auth_internal.c @@ -295,8 +295,8 @@ int oilsAuthInternalCreateSession(osrfMethodContext* ctx) { // fetch the user object jsonObject* idParam = jsonNewNumberStringObject(user_id); - jsonObject* userObj = oilsUtilsCStoreReq( - "open-ils.cstore.direct.actor.user.retrieve", idParam); + jsonObject* userObj = oilsUtilsCStoreReqCtx( + ctx, "open-ils.cstore.direct.actor.user.retrieve", idParam); jsonObjectFree(idParam); if (!userObj) { @@ -392,8 +392,8 @@ int oilsAuthInternalValidate(osrfMethodContext* ctx) { // Confirm user exists, active=true, barred=false, deleted=false params = jsonNewNumberStringObject(user_id); - userObj = oilsUtilsCStoreReq( - "open-ils.cstore.direct.actor.user.retrieve", params); + userObj = oilsUtilsCStoreReqCtx( + ctx, "open-ils.cstore.direct.actor.user.retrieve", params); jsonObjectFree(params); if (userObj && userObj->type != JSON_NULL) { @@ -428,8 +428,8 @@ int oilsAuthInternalValidate(osrfMethodContext* ctx) { int card_ok = 0; params = jsonParseFmt("{\"barcode\":\"%s\"}", barcode); - jsonObject* card = oilsUtilsCStoreReq( - "open-ils.cstore.direct.actor.card.search", params); + jsonObject* card = oilsUtilsCStoreReqCtx( + ctx, "open-ils.cstore.direct.actor.card.search", params); jsonObjectFree(params); if (card && card->type != JSON_NULL) { diff --git a/Open-ILS/src/c-apps/oils_utils.c b/Open-ILS/src/c-apps/oils_utils.c index 155274f99c..4074d9e430 100644 --- a/Open-ILS/src/c-apps/oils_utils.c +++ b/Open-ILS/src/c-apps/oils_utils.c @@ -120,7 +120,7 @@ long oilsFMGetObjectId( const jsonObject* obj ) { return id; } -int oilsUtilsTrackUserActivity(long usr, const char* ewho, const char* ewhat, const char* ehow) { +int oilsUtilsTrackUserActivity(osrfMethodContext* ctx, long usr, const char* ewho, const char* ewhat, const char* ehow) { if (!usr && !(ewho || ewhat || ehow)) return 0; int rowcount = 0; @@ -260,6 +260,42 @@ jsonObject* oilsUtilsQuickReq( const char* service, const char* method, } /** + @brief Perform a remote procedure call, propagating session + locale and timezone + @param service The name of the service to invoke. + @param method The name of the method to call. + @param params The parameters to be passed to the method, if any. + @return A copy of whatever the method returns as a result, or a JSON_NULL if the method + doesn't return anything. + + If the @a params parameter points to a JSON_ARRAY, pass each element of the array + as a separate parameter. If it points to any other kind of jsonObject, pass it as a + single parameter. If it is NULL, pass no parameters. + + The calling code is responsible for freeing the returned object by calling jsonObjectFree(). +*/ +jsonObject* oilsUtilsQuickReqCtx( osrfMethodContext* ctx, const char* service, + const char* method, const jsonObject* params ) { + if(!(service && method && ctx)) return NULL; + + osrfLogDebug(OSRF_LOG_MARK, "oilsUtilsQuickReqCtx(): %s - %s (%s)", service, method, ctx->session->session_tz ); + + // Open an application session with the service, and send the request + osrfAppSession* session = osrfAppSessionClientInit( service ); + osrf_app_session_set_tz(session, ctx->session->session_tz); + int reqid = osrfAppSessionSendRequest( session, params, method, 1 ); + + // Get the response + osrfMessage* omsg = osrfAppSessionRequestRecv( session, reqid, 60 ); + jsonObject* result = jsonObjectClone( osrfMessageGetResult(omsg) ); + + // Clean up + osrfMessageFree(omsg); + osrfAppSessionFree(session); + return result; +} + +/** @brief Call a method of the open-ils.storage service. @param method Name of the method. @param params Parameters to be passed to the method, if any. @@ -293,6 +329,24 @@ jsonObject* oilsUtilsCStoreReq( const char* method, const jsonObject* params ) { return oilsUtilsQuickReq("open-ils.cstore", method, params); } +/** + @brief Call a method of the open-ils.cstore service, context aware. + @param ctx Method context object. + @param method Name of the method. + @param params Parameters to be passed to the method, if any. + @return A copy of whatever the method returns as a result, or a JSON_NULL if the method + doesn't return anything. + + If the @a params parameter points to a JSON_ARRAY, pass each element of the array + as a separate parameter. If it points to any other kind of jsonObject, pass it as a + single parameter. If it is NULL, pass no parameters. + + The calling code is responsible for freeing the returned object by calling jsonObjectFree(). +*/ +jsonObject* oilsUtilsCStoreReqCtx( osrfMethodContext* ctx, const char* method, const jsonObject* params ) { + return oilsUtilsQuickReqCtx(ctx, "open-ils.cstore", method, params); +} + /** @@ -303,11 +357,11 @@ jsonObject* oilsUtilsCStoreReq( const char* method, const jsonObject* params ) { The calling code is responsible for freeing the returned object by calling jsonObjectFree(). */ -jsonObject* oilsUtilsFetchUserByUsername( const char* name ) { +jsonObject* oilsUtilsFetchUserByUsername( osrfMethodContext* ctx, const char* name ) { if(!name) return NULL; jsonObject* params = jsonParseFmt("{\"usrname\":\"%s\"}", name); - jsonObject* user = oilsUtilsQuickReq( - "open-ils.cstore", "open-ils.cstore.direct.actor.user.search", params ); + jsonObject* user = oilsUtilsQuickReqCtx( + ctx, "open-ils.cstore", "open-ils.cstore.direct.actor.user.search", params ); jsonObjectFree(params); long id = oilsFMGetObjectId(user); @@ -326,14 +380,14 @@ jsonObject* oilsUtilsFetchUserByUsername( const char* name ) { The calling code is responsible for freeing the returned object by calling jsonObjectFree(). */ -jsonObject* oilsUtilsFetchUserByBarcode(const char* barcode) { +jsonObject* oilsUtilsFetchUserByBarcode(osrfMethodContext* ctx, const char* barcode) { if(!barcode) return NULL; osrfLogInfo(OSRF_LOG_MARK, "Fetching user by barcode %s", barcode); jsonObject* params = jsonParseFmt("{\"barcode\":\"%s\"}", barcode); - jsonObject* card = oilsUtilsQuickReq( - "open-ils.cstore", "open-ils.cstore.direct.actor.card.search", params ); + jsonObject* card = oilsUtilsQuickReqCtx( + ctx, "open-ils.cstore", "open-ils.cstore.direct.actor.card.search", params ); jsonObjectFree(params); if(!card) @@ -349,8 +403,8 @@ jsonObject* oilsUtilsFetchUserByBarcode(const char* barcode) { // Look up the user in actor.usr params = jsonParseFmt("[%f]", iusr); - jsonObject* user = oilsUtilsQuickReq( - "open-ils.cstore", "open-ils.cstore.direct.actor.user.retrieve", params); + jsonObject* user = oilsUtilsQuickReqCtx( + ctx, "open-ils.cstore", "open-ils.cstore.direct.actor.user.retrieve", params); jsonObjectFree(params); return user; diff --git a/Open-ILS/src/extras/oils_requestor.c b/Open-ILS/src/extras/oils_requestor.c index 73ea934498..7e7baa1b76 100644 --- a/Open-ILS/src/extras/oils_requestor.c +++ b/Open-ILS/src/extras/oils_requestor.c @@ -10,6 +10,7 @@ char* script = NULL; char* authtoken = NULL; +static char* tz = NULL; static int do_request( char* request ); static char* format_response( const jsonObject* o ); @@ -64,6 +65,8 @@ int main( int argc, char* argv[] ) { printf("Connected to OpenSRF network...\n"); + tz = getenv("TZ"); + if( username && password && ( authtoken = oilsUtilsLogin(username, password, "staff", -1 )) ) { printf("Login Session: %s\n", authtoken); @@ -115,6 +118,8 @@ static int do_request( char* request ) { } osrfAppSession* session = osrfAppSessionClientInit(service); + if (tz) osrf_app_session_set_tz(session,tz); + int req_id = osrfAppSessionSendRequest( session, params, method, 1 ); osrfMessage* omsg; -- 2.11.0