/** @brief Given a barcode, fetch the corresponding row from the actor.usr table, if any. @param name The barcode for which to search. @return A Fieldmapper object for the relevant row in the actor.usr table, if it exists; or a JSON_NULL if it doesn't. Look up the barcode in actor.card. Follow a foreign key from there to get a row in actor.usr. The calling code is responsible for freeing the returned object by calling jsonObjectFree(). */ jsonObject* oilsUtilsFetchUserByBarcode(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 ); jsonObjectFree(params); if(!card) return NULL; // No such card // Get the user's id as a double char* usr = oilsFMGetString(card, "usr"); jsonObjectFree(card); if(!usr) return NULL; // No user id (shouldn't happen) double iusr = strtod(usr, NULL); free(usr); // 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); jsonObjectFree(params); return user; }
jsonObject* oilsUtilsFetchWorkstation( long id ) { jsonObject* p = jsonParseFmt("[%ld]", id); jsonObject* r = oilsUtilsQuickReq( "open-ils.storage", "open-ils.storage.direct.actor.workstation.retrieve", p ); jsonObjectFree(p); return r; }
oilsEvent* oilsUtilsCheckPerms( int userid, int orgid, char* permissions[], int size ) { if (!permissions) return NULL; int i; oilsEvent* evt = NULL; // Find the root org unit, i.e. the one with no parent. // Assumption: there is only one org unit with no parent. if (orgid == -1) { jsonObject* where_clause = jsonParse( "{\"parent_ou\":null}" ); jsonObject* org = oilsUtilsQuickReq( "open-ils.cstore", "open-ils.cstore.direct.actor.org_unit.search", where_clause ); jsonObjectFree( where_clause ); orgid = (int)jsonObjectGetNumber( oilsFMGetObject( org, "id" ) ); jsonObjectFree(org); } for( i = 0; i < size && permissions[i]; i++ ) { char* perm = permissions[i]; jsonObject* params = jsonParseFmt("[%d, \"%s\", %d]", userid, perm, orgid); jsonObject* o = oilsUtilsQuickReq( "open-ils.storage", "open-ils.storage.permission.user_has_perm", params ); char* r = jsonObjectToSimpleString(o); if(r && !strcmp(r, "0")) evt = oilsNewEvent3( OSRF_LOG_MARK, OILS_EVENT_PERM_FAILURE, perm, orgid ); jsonObjectFree(params); jsonObjectFree(o); free(r); if(evt) break; } return evt; }
/** @brief Given a username, fetch the corresponding row from the actor.usr table, if any. @param name The username for which to search. @return A Fieldmapper object for the relevant row in the actor.usr table, if it exists; or a JSON_NULL if it doesn't. The calling code is responsible for freeing the returned object by calling jsonObjectFree(). */ jsonObject* oilsUtilsFetchUserByUsername( 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 ); jsonObjectFree(params); long id = oilsFMGetObjectId(user); osrfLogDebug(OSRF_LOG_MARK, "Fetched user %s:%ld", name, id); return user; }
char* oilsUtilsLogin( const char* uname, const char* passwd, const char* type, int orgId ) { if(!(uname && passwd)) return NULL; osrfLogDebug(OSRF_LOG_MARK, "Logging in with username %s", uname ); char* token = NULL; jsonObject* params = jsonParseFmt("[\"%s\"]", uname); jsonObject* o = oilsUtilsQuickReq( "open-ils.auth", "open-ils.auth.authenticate.init", params ); const char* seed = jsonObjectGetString(o); char* passhash = md5sum(passwd); char buf[256]; snprintf(buf, sizeof(buf), "%s%s", seed, passhash); char* fullhash = md5sum(buf); jsonObjectFree(o); jsonObjectFree(params); free(passhash); params = jsonParseFmt( "[\"%s\", \"%s\", \"%s\", \"%d\"]", uname, fullhash, type, orgId ); o = oilsUtilsQuickReq( "open-ils.auth", "open-ils.auth.authenticate.complete", params ); if(o) { const char* tok = jsonObjectGetString( jsonObjectGetKeyConst( jsonObjectGetKey( o,"payload" ), "authtoken" )); if( tok ) token = strdup( tok ); } free(fullhash); jsonObjectFree(params); jsonObjectFree(o); return token; }
char* oilsUtilsFetchOrgSetting( int orgid, const char* setting ) { if(!setting) return NULL; jsonObject* params = jsonParseFmt("[%d, \"%s\"]", orgid, setting ); jsonObject* set = oilsUtilsQuickReq( "open-ils.actor", "open-ils.actor.ou_setting.ancestor_default", params); char* value = jsonObjectToSimpleString( jsonObjectGetKeyConst( set, "value" )); jsonObjectFree(params); jsonObjectFree(set); osrfLogDebug(OSRF_LOG_MARK, "Fetched org [%d] setting: %s => %s", orgid, setting, value); return value; }
int oilsUtilsGetRootOrgId() { // return the cached value if we have it. if (rootOrgId > 0) return rootOrgId; jsonObject* where_clause = jsonParse("{\"parent_ou\":null}"); jsonObject* org = oilsUtilsQuickReq( "open-ils.cstore", "open-ils.cstore.direct.actor.org_unit.search", where_clause ); rootOrgId = (int) jsonObjectGetNumber(oilsFMGetObject(org, "id")); jsonObjectFree(where_clause); jsonObjectFree(org); return rootOrgId; }
/** @brief Implement the "complete" method. @param ctx The method context. @return -1 upon error; zero if successful, and if a STATUS message has been sent to the client to indicate completion; a positive integer if successful but no such STATUS message has been sent. Method parameters: - a hash with some combination of the following elements: - "username" - "barcode" - "password" (hashed with the cached seed; not plaintext) - "type" - "org" - "workstation" The password is required. Either a username or a barcode must also be present. Return to client: Intermediate authentication seed. Validate the password, using the username if available, or the barcode if not. The user must be active, and not barred from logging on. The barcode, if used for authentication, must be active as well. The workstation, if specified, must be valid. Upon deciding whether to allow the logon, return a corresponding event to the client. */ int oilsAuthComplete( osrfMethodContext* ctx ) { OSRF_METHOD_VERIFY_CONTEXT(ctx); const jsonObject* args = jsonObjectGetIndex(ctx->params, 0); const char* uname = jsonObjectGetString(jsonObjectGetKeyConst(args, "username")); const char* password = jsonObjectGetString(jsonObjectGetKeyConst(args, "password")); const char* type = jsonObjectGetString(jsonObjectGetKeyConst(args, "type")); int orgloc = (int) jsonObjectGetNumber(jsonObjectGetKeyConst(args, "org")); const char* workstation = jsonObjectGetString(jsonObjectGetKeyConst(args, "workstation")); const char* barcode = jsonObjectGetString(jsonObjectGetKeyConst(args, "barcode")); const char* ws = (workstation) ? workstation : ""; if( !type ) type = OILS_AUTH_STAFF; if( !( (uname || barcode) && password) ) { return osrfAppRequestRespondException( ctx->session, ctx->request, "username/barcode and password required for method: %s", ctx->method->name ); } oilsEvent* response = NULL; jsonObject* userObj = NULL; int card_active = 1; // boolean; assume active until proven otherwise // Fetch a row from the actor.usr table, by username if available, // or by barcode if not. if(uname) { userObj = oilsUtilsFetchUserByUsername( uname ); if( userObj && JSON_NULL == userObj->type ) { jsonObjectFree( userObj ); userObj = NULL; // username not found } } else if(barcode) { // Read from actor.card by barcode 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 ); jsonObjectFree( params ); if( card && card->type != JSON_NULL ) { // Determine whether the card is active char* card_active_str = oilsFMGetString( card, "active" ); card_active = oilsUtilsIsDBTrue( card_active_str ); free( card_active_str ); // Look up the user who owns the card char* userid = oilsFMGetString( card, "usr" ); jsonObjectFree( card ); params = jsonParseFmt( "[%s]", userid ); free( userid ); userObj = oilsUtilsQuickReq( "open-ils.cstore", "open-ils.cstore.direct.actor.user.retrieve", params ); jsonObjectFree( params ); if( userObj && JSON_NULL == userObj->type ) { // user not found (shouldn't happen, due to foreign key) jsonObjectFree( userObj ); userObj = NULL; } } } if(!userObj) { response = oilsNewEvent( OSRF_LOG_MARK, OILS_EVENT_AUTH_FAILED ); osrfLogInfo(OSRF_LOG_MARK, "failed login: username=%s, barcode=%s, workstation=%s", uname, (barcode ? barcode : "(none)"), ws ); osrfAppRespondComplete( ctx, oilsEventToJSON(response) ); oilsEventFree(response); return 0; // No such user } // Such a user exists. Now see if he or she has the right credentials. int passOK = -1; if(uname) passOK = oilsAuthVerifyPassword( ctx, userObj, uname, password ); else if (barcode) passOK = oilsAuthVerifyPassword( ctx, userObj, barcode, password ); if( passOK < 0 ) { jsonObjectFree(userObj); return passOK; } // See if the account is active char* active = oilsFMGetString(userObj, "active"); if( !oilsUtilsIsDBTrue(active) ) { if( passOK ) response = oilsNewEvent( OSRF_LOG_MARK, "PATRON_INACTIVE" ); else response = oilsNewEvent( OSRF_LOG_MARK, OILS_EVENT_AUTH_FAILED ); osrfAppRespondComplete( ctx, oilsEventToJSON(response) ); oilsEventFree(response); jsonObjectFree(userObj); free(active); return 0; } free(active); osrfLogInfo( OSRF_LOG_MARK, "Fetching card by barcode %s", barcode ); if( !card_active ) { osrfLogInfo( OSRF_LOG_MARK, "barcode %s is not active, returning event", barcode ); response = oilsNewEvent( OSRF_LOG_MARK, "PATRON_CARD_INACTIVE" ); osrfAppRespondComplete( ctx, oilsEventToJSON( response ) ); oilsEventFree( response ); jsonObjectFree( userObj ); return 0; } // See if the user is even allowed to log in if( oilsAuthCheckLoginPerm( ctx, userObj, type ) == -1 ) { jsonObjectFree(userObj); return 0; } // If a workstation is defined, add the workstation info if( workstation != NULL ) { osrfLogDebug(OSRF_LOG_MARK, "Workstation is %s", workstation); response = oilsAuthVerifyWorkstation( ctx, userObj, workstation ); if(response) { jsonObjectFree(userObj); osrfAppRespondComplete( ctx, oilsEventToJSON(response) ); oilsEventFree(response); return 0; } } else { // Otherwise, use the home org as the workstation org on the user char* orgid = oilsFMGetString(userObj, "home_ou"); oilsFMSetString(userObj, "ws_ou", orgid); free(orgid); } char* freeable_uname = NULL; if(!uname) { uname = freeable_uname = oilsFMGetString( userObj, "usrname" ); } if( passOK ) { response = oilsAuthHandleLoginOK( userObj, uname, type, orgloc, workstation ); } else { response = oilsNewEvent( OSRF_LOG_MARK, OILS_EVENT_AUTH_FAILED ); osrfLogInfo(OSRF_LOG_MARK, "failed login: username=%s, barcode=%s, workstation=%s", uname, (barcode ? barcode : "(none)"), ws ); } jsonObjectFree(userObj); osrfAppRespondComplete( ctx, oilsEventToJSON(response) ); oilsEventFree(response); if(freeable_uname) free(freeable_uname); return 0; }
/** @brief Call a method of the open-ils.cstore service. @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* oilsUtilsCStoreReq( const char* method, const jsonObject* params ) { return oilsUtilsQuickReq("open-ils.cstore", method, params); }