From 36cc9398c711d282007e1340a3c5ef1182d20f87 Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Wed, 16 Oct 2024 20:36:53 -0400 Subject: [PATCH] js: Move storePermission to C. --- core/core.js | 48 ++--------------------- src/ssb.js.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 110 insertions(+), 44 deletions(-) diff --git a/core/core.js b/core/core.js index edb1b611..0b43eb5b 100644 --- a/core/core.js +++ b/core/core.js @@ -387,9 +387,9 @@ async function getProcessBlob(blobId, key, options) { } else if (process.app) { return process.app .makeFunction(['requestPermission'])(permission) - .then(function (value) { + .then(async function (value) { if (value == 'allow') { - storePermission( + await ssb.setUserPermission( user, options.packageOwner, options.packageName, @@ -401,7 +401,7 @@ async function getProcessBlob(blobId, key, options) { } else if (value == 'allow once') { return true; } else if (value == 'deny') { - storePermission( + await ssb.setUserPermission( user, options.packageOwner, options.packageName, @@ -748,7 +748,7 @@ async function getProcessBlob(blobId, key, options) { }; process.resetPermission = async function resetPermission(permission) { let user = process?.credentials?.session?.name; - storePermission( + await ssb.setUserPermission( user, options?.packageOwner, options?.packageName, @@ -1245,44 +1245,4 @@ loadSettings() exit(1); }); -/** - * TODOC - * @param {*} user - * @param {*} packageOwner - * @param {*} packageName - * @param {*} permission - * @param {*} allow - */ -async function storePermission(user, packageOwner, packageName, permission, allow) { - let settings = await loadSettings(); - if (!settings.userPermissions) { - settings.userPermissions = {}; - } - if (!settings.userPermissions[user]) { - settings.userPermissions[user] = {}; - } - if (!settings.userPermissions[user][packageOwner]) { - settings.userPermissions[user][packageOwner] = {}; - } - if (!settings.userPermissions[user][packageOwner][packageName]) { - settings.userPermissions[user][packageOwner][packageName] = {}; - } - if ( - settings.userPermissions[user][packageOwner][packageName][ - permission - ] !== allow - ) { - if (allow === undefined) { - delete settings.userPermissions[user][packageOwner][packageName][ - permission - ]; - } else { - settings.userPermissions[user][packageOwner][packageName][ - permission - ] = allow; - } - return setGlobalSettings(settings); - } -} - export {invoke, getProcessBlob}; diff --git a/src/ssb.js.c b/src/ssb.js.c index 2d5fdef6..b582e0d1 100644 --- a/src/ssb.js.c +++ b/src/ssb.js.c @@ -2394,6 +2394,111 @@ static JSValue _tf_ssb_sync(JSContext* context, JSValueConst this_val, int argc, return JS_UNDEFINED; } +typedef struct _set_user_permission_t +{ + tf_ssb_t* ssb; + JSContext* context; + const char* user; + const char* package_owner; + const char* package_name; + const char* permission; + bool allow; + bool result; + JSValue promise[2]; +} set_user_permission_t; + +static void _tf_ssb_set_user_permission_work(tf_ssb_t* ssb, void* user_data) +{ + set_user_permission_t* work = user_data; + + JSMallocFunctions funcs = { 0 }; + tf_get_js_malloc_functions(&funcs); + JSRuntime* runtime = JS_NewRuntime2(&funcs, NULL); + JSContext* context = JS_NewContext(runtime); + + /* XXX: Do this with one DB writer. */ + const char* settings = tf_ssb_db_get_property(ssb, "core", "settings"); + if (settings) + { + JSValue settings_value = JS_ParseJSON(context, settings, strlen(settings), NULL); + JSValue user_permissions = JS_GetPropertyStr(context, settings_value, "userPermissions"); + if (JS_IsUndefined(user_permissions)) + { + user_permissions = JS_NewObject(context); + JS_SetPropertyStr(context, settings_value, "userPermissions", JS_DupValue(context, user_permissions)); + } + JSValue user = JS_GetPropertyStr(context, user_permissions, work->user); + if (JS_IsUndefined(user)) + { + user = JS_NewObject(context); + JS_SetPropertyStr(context, user_permissions, work->user, JS_DupValue(context, user)); + } + JSValue package_owner = JS_GetPropertyStr(context, user, work->package_owner); + if (JS_IsUndefined(package_owner)) + { + package_owner = JS_NewObject(context); + JS_SetPropertyStr(context, user, work->package_owner, JS_DupValue(context, package_owner)); + } + JSValue package_name = JS_GetPropertyStr(context, package_owner, work->package_name); + if (JS_IsUndefined(package_name)) + { + package_name = JS_NewObject(context); + JS_SetPropertyStr(context, package_owner, work->package_name, package_name); + } + JSValue permission = JS_GetPropertyStr(context, package_name, work->permission); + if (JS_ToBool(context, permission) != work->allow) + { + JS_SetPropertyStr(context, package_name, work->permission, JS_NewBool(context, work->allow)); + JSValue settings_json = JS_JSONStringify(context, settings_value, JS_NULL, JS_NULL); + const char* settings_string = JS_ToCString(context, settings_json); + work->result = tf_ssb_db_set_property(ssb, "core", "settings", settings_string); + JS_FreeCString(context, settings_string); + JS_FreeValue(context, settings_json); + } + else + { + work->result = true; + } + } + + JS_FreeContext(context); + JS_FreeRuntime(runtime); +} + +static void _tf_ssb_set_user_permission_after_work(tf_ssb_t* ssb, int status, void* user_data) +{ + set_user_permission_t* work = user_data; + JSContext* context = work->context; + JS_FreeCString(context, work->user); + JS_FreeCString(context, work->package_owner); + JS_FreeCString(context, work->package_name); + JS_FreeCString(context, work->permission); + JSValue error = JS_Call(context, work->result ? work->promise[0] : work->promise[0], JS_UNDEFINED, 0, NULL); + tf_util_report_error(context, error); + JS_FreeValue(context, error); + JS_FreeValue(context, work->promise[0]); + JS_FreeValue(context, work->promise[1]); + tf_free(work); +} + +static JSValue _tf_ssb_set_user_permission(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) +{ + set_user_permission_t* set = tf_malloc(sizeof(set_user_permission_t)); + *set = (set_user_permission_t) + { + .ssb = JS_GetOpaque(this_val, _tf_ssb_classId), + .context = context, + .user = JS_ToCString(context, argv[0]), + .package_owner = JS_ToCString(context, argv[1]), + .package_name = JS_ToCString(context, argv[2]), + .permission = JS_ToCString(context, argv[3]), + .allow = JS_ToBool(context, argv[4]), + }; + JSValue result = JS_NewPromiseCapability(context, set->promise); + tf_ssb_run_work(set->ssb, _tf_ssb_set_user_permission_work, _tf_ssb_set_user_permission_after_work, set); + return result; +} + void tf_ssb_register(JSContext* context, tf_ssb_t* ssb) { JS_NewClassID(&_tf_ssb_classId); @@ -2420,6 +2525,7 @@ void tf_ssb_register(JSContext* context, tf_ssb_t* ssb) JS_SetPropertyStr(context, object, "getPrivateKey", JS_NewCFunction(context, _tf_ssb_getPrivateKey, "getPrivateKey", 2)); JS_SetPropertyStr(context, object, "privateMessageEncrypt", JS_NewCFunction(context, _tf_ssb_private_message_encrypt, "privateMessageEncrypt", 4)); JS_SetPropertyStr(context, object, "privateMessageDecrypt", JS_NewCFunction(context, _tf_ssb_private_message_decrypt, "privateMessageDecrypt", 3)); + JS_SetPropertyStr(context, object, "setUserPermission", JS_NewCFunction(context, _tf_ssb_set_user_permission, "setUserPermission", 5)); /* Write. */ JS_SetPropertyStr(context, object, "appendMessageWithIdentity", JS_NewCFunction(context, _tf_ssb_appendMessageWithIdentity, "appendMessageWithIdentity", 3));