char* SELECT ( osrfMethodContext*, jsonObject*, const jsonObject*, const jsonObject*,
const jsonObject*, const jsonObject*, const jsonObject*, const jsonObject*, int );
+static osrfStringArray* getPermLocationCache( osrfMethodContext*, const char* );
+static void setPermLocationCache( osrfMethodContext*, const char*, osrfStringArray* );
+
void userDataFree( void* );
static void sessionDataFree( char*, void* );
+static void pcacheFree( char*, void* );
static int obj_is_true( const jsonObject* obj );
static const char* json_type( int code );
static const char* get_primitive( osrfHash* field );
static void clear_query_stack( void );
static const jsonObject* verifyUserPCRUD( osrfMethodContext* );
-static int verifyObjectPCRUD( osrfMethodContext*, const jsonObject* );
+static int verifyObjectPCRUD( osrfMethodContext*, const jsonObject*, const int );
static const char* org_tree_root( osrfMethodContext* ctx );
static jsonObject* single_hash( const char* key, const char* value );
static int max_flesh_depth = 100;
+static int perm_at_threshold = 5;
static int enforce_pcrud = 0; // Boolean
static char* modulename = NULL;
that it will free whatever else needs freeing.
*/
static void sessionDataFree( char* key, void* item ) {
- if( !strcmp( key, "xact_id" )
- || !strcmp( key, "authkey" ) ) {
+ if( !strcmp( key, "xact_id" ) || !strcmp( key, "authkey" ) )
free( item );
- } else if( !strcmp( key, "user_login" ) )
+ else if( !strcmp( key, "user_login" ) )
jsonObjectFree( (jsonObject*) item );
+ else if( !strcmp( key, "pcache" ) )
+ osrfHashFree( (osrfHash*) item );
+}
+
+static void pcacheFree( char* key, void* item ) {
+ osrfStringArrayFree( (osrfStringArray*) item );
}
/**
/*@}*/
/**
+ @brief Stash the location for a particular perm in the sessionData cache
+ @param ctx Pointer to the method context.
+ @param perm Name of the permission we're looking at
+ @param array StringArray of perm location ids
+*/
+static void setPermLocationCache( osrfMethodContext* ctx, const char* perm, osrfStringArray* locations ) {
+ 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;
+ }
+
+ osrfHash* pcache = osrfHashGet(cache, "pcache");
+
+ if( NULL == pcache ) {
+ pcache = osrfNewHash();
+ osrfHashSetCallback( pcache, &pcacheFree );
+ osrfHashSet( cache, pcache, "pcache" );
+ }
+
+ if( perm && locations )
+ osrfHashSet( pcache, locations, strdup(perm) );
+ }
+}
+
+/**
+ @brief Grab stashed location for a particular perm in the sessionData cache
+ @param ctx Pointer to the method context.
+ @param perm Name of the permission we're looking at
+*/
+static osrfStringArray* getPermLocationCache( osrfMethodContext* ctx, const char* perm ) {
+ if( ctx && ctx->session ) {
+ osrfAppSession* session = ctx->session;
+ osrfHash* cache = session->userData;
+ if( cache ) {
+ osrfHash* pcache = osrfHashGet(cache, "pcache");
+ if( pcache ) {
+ return osrfHashGet( pcache, perm );
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
@brief Save the user's login in the userData for the current application session.
@param ctx Pointer to the method context.
@param user_login Pointer to the user login object to be cached (we cache the original,
jsonObject* cur = 0;
unsigned long res_idx = 0;
while((cur = jsonObjectGetIndex( obj, res_idx++ ) )) {
- if( enforce_pcrud && !verifyObjectPCRUD( ctx, cur ))
+ if( enforce_pcrud && !verifyObjectPCRUD( ctx, cur, obj->size ))
continue;
osrfAppRespond( ctx, cur );
}
jsonObject* cur;
unsigned long res_idx = 0;
while((cur = jsonObjectGetIndex( obj, res_idx++ ) )) {
- if( enforce_pcrud && !verifyObjectPCRUD( ctx, cur ))
+ if( enforce_pcrud && !verifyObjectPCRUD( ctx, cur, obj->size ))
continue; // Suppress due to lack of permission
else
osrfAppRespond( ctx,
}
if( enforce_pcrud )
- return verifyObjectPCRUD( ctx, param );
+ return verifyObjectPCRUD( ctx, param, 1 );
else
return 1;
}
The @a obj parameter points to a JSON_HASH of column values, keyed on column name.
*/
-static int verifyObjectPCRUD ( osrfMethodContext* ctx, const jsonObject* obj ) {
+static int verifyObjectPCRUD ( osrfMethodContext* ctx, const jsonObject* obj, const int rs_size ) {
dbhandle = writehandle;
// In other words permissions are additive.
int i = 0;
while( (perm = osrfStringArrayGetString(permission, i++)) ) {
+ dbi_result result;
+
+ osrfStringArray* pcache = NULL;
+ if (rs_size > perm_at_threshold) { // grab and cache locations of user perms
+ pcache = getPermLocationCache(ctx, perm);
+
+ if (!pcache) {
+ pcache = osrfNewStringArray(0);
+
+ result = dbi_conn_queryf(
+ writehandle,
+ "SELECT permission.usr_has_perm_at_all(%d, '%s') AS at;",
+ userid,
+ perm
+ );
+
+ if( result ) {
+ osrfLogDebug(
+ OSRF_LOG_MARK,
+ "Received a result for permission [%s] for user %d",
+ perm,
+ userid
+ );
+
+ if( dbi_result_first_row( result )) {
+ do {
+ jsonObject* return_val = oilsMakeJSONFromResult( result );
+ osrfStringArrayAdd( pcache, jsonObjectGetString( jsonObjectGetKeyConst( return_val, "at" ) ) );
+ jsonObjectFree( return_val );
+ } while( dbi_result_next_row( result ));
+
+ setPermLocationCache(ctx, perm, pcache);
+ }
+
+ dbi_result_free( result );
+ }
+ }
+ }
+
int j = 0;
while( (context_org = osrfStringArrayGetString( context_org_array, j++ )) ) {
- dbi_result result;
+
+ if (rs_size > perm_at_threshold) {
+ if (osrfStringArrayContains( pcache, context_org )) {
+ OK = 1;
+ break;
+ }
+ }
if( pkey_value ) {
osrfLogDebug(
}
}
+ if (rs_size > perm_at_threshold) break;
+
osrfLogDebug( OSRF_LOG_MARK,
"Checking non-object permission [%s] for user %d at org %d",
perm, userid, atoi(context_org) );
}
}
+
if( OK )
break;
}
jsonObjectFree( list );
if( enforce_pcrud ) {
- if(!verifyObjectPCRUD( ctx, obj )) {
+ if(!verifyObjectPCRUD( ctx, obj, 1 )) {
jsonObjectFree( obj );
growing_buffer* msg = buffer_init( 128 );
id = oilsFMGetString( jsonObjectGetIndex(ctx->params, _obj_pos), pkey );
} else {
- if( enforce_pcrud && !verifyObjectPCRUD( ctx, NULL )) {
+ if( enforce_pcrud && !verifyObjectPCRUD( ctx, NULL, 1 )) {
osrfAppRespondComplete( ctx, NULL );
return -1;
}