LP#1485374: add way for C code to make TZ-aware subrequests
authorGalen Charlton <gmc@esilibrary.com>
Tue, 23 Feb 2016 17:09:15 +0000 (12:09 -0500)
committerKathy Lussier <klussier@masslnc.org>
Fri, 27 Jan 2017 19:45:50 +0000 (14:45 -0500)
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 <gmc@esilibrary.com>
Signed-off-by: Mike Rylander <mrylander@gmail.com>
Signed-off-by: Kathy Lussier <klussier@masslnc.org>
Conflicts:
Open-ILS/src/c-apps/oils_auth.c

Signed-off-by: Jason Stephenson <jason@sigio.com>
Signed-off-by: Kathy Lussier <klussier@masslnc.org>
Open-ILS/include/openils/oils_utils.h
Open-ILS/src/c-apps/oils_auth.c
Open-ILS/src/c-apps/oils_auth_internal.c
Open-ILS/src/c-apps/oils_utils.c
Open-ILS/src/extras/oils_requestor.c

index 6b391f2..839c582 100644 (file)
@@ -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)
index 068e0f1..628efc8 100644 (file)
@@ -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()
index a2fa08e..96ad193 100644 (file)
@@ -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) {
index 155274f..4074d9e 100644 (file)
@@ -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;
index 73ea934..7e7baa1 100644 (file)
@@ -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;