From f787eb077bcf813851c38230e623c694f1dd988b Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Wed, 27 Jul 2022 00:27:10 +0000 Subject: [PATCH] An experiment in requesting permissions and some related fixes. git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3937 ed5197a5-7fde-0310-b194-c3ffbd925b24 --- core/app.js | 2 ++ core/client.js | 17 +++++++++++ core/core.js | 77 ++++++++++++++++++++++++++++++++++++++++++++++++- core/index.html | 2 ++ src/task.c | 9 ++++-- src/task.h | 2 +- src/util.js.c | 10 ++----- 7 files changed, 108 insertions(+), 11 deletions(-) diff --git a/core/app.js b/core/app.js index 7a809a8f..b61a3e39 100644 --- a/core/app.js +++ b/core/app.js @@ -141,6 +141,8 @@ function socket(request, response, client) { if (process) { core.enableStats(process, message.enabled); } + } else if (message.action == 'permission') { + core.setPermission(process, message.id, message.granted); } else { if (process && process.eventHandlers['message']) { await core.invoke(process.eventHandlers['message'], [message]); diff --git a/core/client.js b/core/client.js index ac8f544a..d49a7af0 100644 --- a/core/client.js +++ b/core/client.js @@ -24,6 +24,7 @@ const k_api = { error: {args: ['error'], func: api_error}, localStorageSet: {args: ['key', 'value'], func: api_localStorageSet}, localStorageGet: {args: ['key'], func: api_localStorageGet}, + requestPermission: {args: ['permission', 'id'], func: api_requestPermission}, }; window.addEventListener("keydown", function(event) { @@ -440,6 +441,22 @@ function api_localStorageGet(key, value) { send({message: 'localStorage', key: key, value: window.localStorage.getItem('app:' + key)}); } +function api_requestPermission(permission, id) { + let permissions = document.getElementById('permissions'); + let div = document.createElement('div'); + div.appendChild(document.createTextNode(permission)); + for (let action of ['allow', 'allow once', 'deny once', 'deny']) { + let button = document.createElement('button'); + button.innerText = action; + button.onclick = function() { + send({action: 'permission', id: id, granted: action}); + permissions.removeChild(div); + } + div.appendChild(button); + } + permissions.appendChild(div); +} + function receive(message) { if (message && message.action == "session") { setStatusMessage("🟢 Executing...", kStatusColor); diff --git a/core/core.js b/core/core.js index 25c98d31..f8aada0a 100644 --- a/core/core.js +++ b/core/core.js @@ -149,6 +149,8 @@ async function getProcessBlob(blobId, key, options) { process.task = null; delete gProcesses[key]; }; + process.promises = {}; + process.nextPromise = 1; var imports = { 'core': { 'broadcast': broadcast.bind(process), @@ -172,6 +174,47 @@ async function getProcessBlob(blobId, key, options) { 'user': getUser(process, process), 'apps': user => getApps(user, process), 'getSockets': getSockets, + 'permissionTest': function(permission) { + let id = process.nextPromise++; + let promise = new Promise(function(resolve, reject) { + process.promises[id] = {resolve: resolve, reject: reject}; + }); + let user = process?.credentials?.session?.name; + if (!user || !options?.packageOwner || !options?.packageName) { + process.promises[id].reject(false); + } else if (gGlobalSettings.userPermissions && + gGlobalSettings.userPermissions[user] && + gGlobalSettings.userPermissions[user][options.packageOwner] && + gGlobalSettings.userPermissions[user][options.packageOwner][options.packageName] && + gGlobalSettings.userPermissions[user][options.packageOwner][options.packageName][permission] !== undefined) { + if (gGlobalSettings.userPermissions[user][options.packageOwner][options.packageName][permission]) { + process.promises[id].resolve(true); + } else { + process.promises[id].reject(false); + } + + } else { + process.app.send({action: 'requestPermission', permission: permission, id: id}); + promise.then(function(value) { + if (value == 'allow') { + storePermission(user, options.packageOwner, options.packageName, permission, true); + return true; + } else if (value == 'allow once') { + return true; + } + return false; + }).catch(function(value) { + if (value == 'deny') { + storePermission(user, options.packageOwner, options.packageName, permission, false); + return false; + } else if (value == 'deny once') { + return false; + } + return false; + }); + } + return promise; + }, } }; if (options.api) { @@ -646,10 +689,42 @@ loadSettings().then(function() { exit(1); }); +function setPermission(process, id, allow) { + if (process.promises[id]) { + if (allow == 'allow' || allow == 'allow once') { + process.promises[id].resolve(allow); + } else { + process.promises[id].reject(allow); + } + delete process.promises[id]; + } +} + +function storePermission(user, packageOwner, packageName, permission, allow) { + if (!gGlobalSettings.userPermissions) { + gGlobalSettings.userPermissions = {}; + } + if (!gGlobalSettings.userPermissions[user]) { + gGlobalSettings.userPermissions[user] = {}; + } + if (!gGlobalSettings.userPermissions[user][packageOwner]) { + gGlobalSettings.userPermissions[user][packageOwner] = {}; + } + if (!gGlobalSettings.userPermissions[user][packageOwner][packageName]) { + gGlobalSettings.userPermissions[user][packageOwner][packageName] = {}; + } + if (gGlobalSettings.userPermissions[user][packageOwner][packageName][permission] !== allow) { + gGlobalSettings.userPermissions[user][packageOwner][packageName][permission] = allow; + print('STORE', JSON.stringify(gGlobalSettings)); + setGlobalSettings(gGlobalSettings); + } +} + export { gGlobalSettings as globalSettings, setGlobalSettings, enableStats, invoke, - getSessionProcessBlob + getSessionProcessBlob, + setPermission, }; diff --git a/core/index.html b/core/index.html index 27f38b11..0f2da233 100644 --- a/core/index.html +++ b/core/index.html @@ -16,6 +16,8 @@ trace stats + +
diff --git a/src/task.c b/src/task.c index 672adcc0..653338fd 100644 --- a/src/task.c +++ b/src/task.c @@ -270,7 +270,7 @@ static void _export_record_release_for_task(tf_task_t* task, taskid_t task_id) } } -void tf_task_send_error_to_parent(tf_task_t* task, JSValue error) +bool tf_task_send_error_to_parent(tf_task_t* task, JSValue error) { if (task && task->_parent) { @@ -279,7 +279,9 @@ void tf_task_send_error_to_parent(tf_task_t* task, JSValue error) tf_serialize_store(task, task->_parent, &buffer, &size, error); tf_packetstream_send(tf_taskstub_get_stream(task->_parent), kTaskError, buffer, size); tf_free(buffer); + return true; } + return false; } static const char* _task_loadFile(const char* fileName) @@ -337,7 +339,10 @@ int tf_task_execute(tf_task_t* task, const char* fileName) if (source) { JSValue result = JS_Eval(task->_context, source, strlen(source), fileName, JS_EVAL_TYPE_MODULE); - tf_util_report_error(task->_context, result); + if (tf_util_report_error(task->_context, result)) + { + printf("Reported an error.\n"); + } if (!JS_IsError(task->_context, result) && !JS_IsException(result)) { executed = true; diff --git a/src/task.h b/src/task.h index 1127646a..94bf5e37 100644 --- a/src/task.h +++ b/src/task.h @@ -73,4 +73,4 @@ void tf_task_report_error(tf_task_t* task, JSValue error); JSValue tf_try_get_typed_array_buffer(JSContext *ctx, JSValueConst obj, size_t *pbyte_offset, size_t *pbyte_length, size_t *pbytes_per_element); uint8_t *tf_try_get_array_buffer(JSContext *ctx, size_t *psize, JSValueConst obj); -void tf_task_send_error_to_parent(tf_task_t* task, JSValue error); +bool tf_task_send_error_to_parent(tf_task_t* task, JSValue error); diff --git a/src/util.js.c b/src/util.js.c index f867fa48..9bd3b488 100644 --- a/src/util.js.c +++ b/src/util.js.c @@ -123,20 +123,16 @@ bool tf_util_report_error(JSContext* context, JSValue value) JS_FreeValue(context, stack); tf_task_t* task = tf_task_get(context); - if (task) + if (!task || !tf_task_send_error_to_parent(task, value)) { - tf_task_send_error_to_parent(task, value); + js_std_dump_error(context); } is_error = true; } else if (JS_IsException(value)) { tf_task_t* task = tf_task_get(context); - if (task) - { - tf_task_send_error_to_parent(task, value); - } - else + if (!task || !tf_task_send_error_to_parent(task, value)) { js_std_dump_error(context); }