diff --git a/core/core.js b/core/core.js index 3133e8c9..0b34bb71 100644 --- a/core/core.js +++ b/core/core.js @@ -97,32 +97,6 @@ function getUser(caller, process) { }; } -async function getApps(user, process) { - if ( - process.credentials && - process.credentials.session && - process.credentials.session.name - ) { - if (user && user !== process.credentials.session.name && user !== 'core') { - return {}; - } else if (!user) { - user = process.credentials.session.name; - } - } - if (user) { - let db = new Database(user); - try { - let names = JSON.parse(await db.get('apps')); - let result = {}; - for (let name of names) { - result[name] = await db.get('path:' + name); - } - return result; - } catch {} - } - return {}; -} - function postMessageInternal(from, to, message) { if (to.eventHandlers['message']) { return invoke(to.eventHandlers['message'], [getUser(from, from), message]); @@ -220,7 +194,6 @@ async function getProcessBlob(blobId, key, options) { let settings = await loadSettings(); return settings?.permissions?.[user] ?? []; }, - apps: (user) => getApps(user, process), getSockets: getSockets, permissionTest: async function (permission) { let user = process?.credentials?.session?.name; diff --git a/src/api.js.c b/src/api.js.c index 15395599..8b08b9f6 100644 --- a/src/api.js.c +++ b/src/api.js.c @@ -1,11 +1,159 @@ #include "api.js.h" #include "log.h" +#include "mem.h" +#include "ssb.db.h" +#include "ssb.h" +#include "task.h" +#include "util.js.h" #include +typedef struct _app_path_pair_t +{ + const char* app; + const char* path; +} app_path_pair_t; + +typedef struct _get_apps_t +{ + app_path_pair_t* apps; + int count; + JSContext* context; + JSValue promise[2]; + char user[]; +} get_apps_t; + +static void _tf_api_core_apps_work(tf_ssb_t* ssb, void* user_data) +{ + get_apps_t* work = user_data; + + JSMallocFunctions funcs = { 0 }; + tf_get_js_malloc_functions(&funcs); + JSRuntime* runtime = JS_NewRuntime2(&funcs, NULL); + JSContext* context = JS_NewContext(runtime); + + const char* apps = tf_ssb_db_get_property(ssb, work->user, "apps"); + if (apps) + { + JSValue apps_array = JS_ParseJSON(context, apps, strlen(apps), NULL); + if (JS_IsArray(context, apps_array)) + { + int length = tf_util_get_length(context, apps_array); + for (int i = 0; i < length; i++) + { + JSValue name = JS_GetPropertyUint32(context, apps_array, i); + const char* name_string = JS_ToCString(context, name); + if (name_string) + { + work->apps = tf_resize_vec(work->apps, sizeof(app_path_pair_t) * (work->count + 1)); + work->apps[work->count].app = tf_strdup(name_string); + size_t size = strlen("path:") + strlen(name_string) + 1; + char* path_key = tf_malloc(size); + snprintf(path_key, size, "path:%s", name_string); + work->apps[work->count].path = tf_ssb_db_get_property(ssb, work->user, path_key); + tf_free(path_key); + work->count++; + } + JS_FreeCString(context, name_string); + JS_FreeValue(context, name); + } + } + JS_FreeValue(context, apps_array); + } + tf_free((void*)apps); + + JS_FreeContext(context); + JS_FreeRuntime(runtime); +} + +static void _tf_api_core_apps_after_work(tf_ssb_t* ssb, int status, void* user_data) +{ + get_apps_t* work = user_data; + JSContext* context = work->context; + JSValue result = JS_NewObject(context); + for (int i = 0; i < work->count; i++) + { + JS_SetPropertyStr(context, result, work->apps[i].app, JS_NewString(context, work->apps[i].path)); + } + JSValue error = JS_Call(context, work->promise[0], JS_UNDEFINED, 1, &result); + tf_util_report_error(context, error); + JS_FreeValue(context, error); + JS_FreeValue(context, result); + JS_FreeValue(context, work->promise[0]); + JS_FreeValue(context, work->promise[1]); + for (int i = 0; i < work->count; i++) + { + tf_free((void*)work->apps[i].app); + tf_free((void*)work->apps[i].path); + } + tf_free(work->apps); + tf_free(work); +} + +static JSValue _tf_api_core_apps(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv, int magic, JSValue* data) +{ + JSValue result = JS_UNDEFINED; + JSValue user = argv[0]; + JSValue process = data[0]; + const char* user_string = JS_IsString(user) ? JS_ToCString(context, user) : NULL; + + if (JS_IsObject(process)) + { + JSValue credentials = JS_GetPropertyStr(context, process, "credentials"); + if (JS_IsObject(credentials)) + { + JSValue session = JS_GetPropertyStr(context, credentials, "session"); + if (JS_IsObject(session)) + { + JSValue session_name = JS_GetPropertyStr(context, session, "name"); + const char* session_name_string = JS_IsString(session_name) ? JS_ToCString(context, session_name) : NULL; + if (user_string && session_name_string && strcmp(user_string, session_name_string) && strcmp(user_string, "core")) + { + JS_FreeCString(context, user_string); + user_string = NULL; + } + else if (!user_string) + { + user_string = session_name_string; + session_name_string = NULL; + } + JS_FreeCString(context, session_name_string); + JS_FreeValue(context, session_name); + } + JS_FreeValue(context, session); + } + JS_FreeValue(context, credentials); + } + + if (user_string) + { + get_apps_t* work = tf_malloc(sizeof(get_apps_t) + strlen(user_string) + 1); + *work = (get_apps_t) { + .context = context, + }; + memcpy(work->user, user_string, strlen(user_string) + 1); + result = JS_NewPromiseCapability(context, work->promise); + + tf_task_t* task = tf_task_get(context); + tf_ssb_t* ssb = tf_task_get_ssb(task); + tf_ssb_run_work(ssb, _tf_api_core_apps_work, _tf_api_core_apps_after_work, work); + } + else + { + result = JS_NewObject(context); + } + JS_FreeCString(context, user_string); + return result; +} + static JSValue _tf_api_register_imports(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) { + JSValue imports = argv[0]; + JSValue process = argv[1]; + JSValue core = JS_GetPropertyStr(context, imports, "core"); + JS_SetPropertyStr(context, core, "apps", JS_NewCFunctionData(context, _tf_api_core_apps, 1, 0, 1, &process)); + JS_FreeValue(context, core); return JS_UNDEFINED; }