diff --git a/core/app.js b/core/app.js index 558ea7ae..2a8389b8 100644 --- a/core/app.js +++ b/core/app.js @@ -158,6 +158,10 @@ function socket(request, response, client) { if (process) { core.enableStats(process, message.enabled); } + } else if (message.action == 'resetPermission') { + if (process) { + process.resetPermission(message.permission); + } } else if (message.message == 'tfrpc') { if (message.id && g_calls[message.id]) { if (message.error !== undefined) { diff --git a/core/client.js b/core/client.js index 60318d7e..5d7c1748 100644 --- a/core/client.js +++ b/core/client.js @@ -2,6 +2,7 @@ let gSocket; let gCredentials; +let gPermissions; let gCurrentFile; let gFiles = {}; @@ -504,6 +505,64 @@ function api_print() { console.log('app>', ...arguments); } +function hidePermissions() { + let permissions = document.getElementById('permissions_settings'); + while (permissions.firstChild) { + permissions.removeChild(permissions.firstChild); + } + permissions.style.visibility = 'hidden'; +} + +function showPermissions() { + let permissions = document.getElementById('permissions_settings'); + + let container = document.createElement('div'); + container.classList.add('permissions_contents'); + + let div = document.createElement('div'); + div.appendChild(document.createTextNode('This app has the following permission:')); + for (let key of Object.keys(gPermissions || {})) { + let row = document.createElement('div'); + + let span = document.createElement('span'); + span.appendChild(document.createTextNode(key)); + row.appendChild(span); + + span = document.createElement('span'); + span.appendChild(document.createTextNode(': ')); + row.appendChild(span); + + span = document.createElement('span'); + span.appendChild(document.createTextNode(gPermissions[key] ? '✅ Allowed' : '❌ Denied')); + row.appendChild(span); + + span = document.createElement('span'); + span.appendChild(document.createTextNode(' ')); + row.appendChild(span); + + let button = document.createElement('button'); + button.innerText = 'Reset'; + button.onclick = function() { + send({action: "resetPermission", permission: key}); + }; + row.appendChild(button); + div.appendChild(row); + } + container.appendChild(div); + + div = document.createElement('div'); + let button = document.createElement('button'); + button.innerText = 'Close'; + button.onclick = function() { + hidePermissions(); + } + div.appendChild(button); + container.appendChild(div); + + permissions.appendChild(container); + permissions.style.visibility = 'visible'; +} + function _receive_websocket_message(message) { if (message && message.action == "session") { setStatusMessage("🟢 Executing...", kStatusColor); @@ -513,6 +572,13 @@ function _receive_websocket_message(message) { let parent_enabled = message.parentApp; document.getElementById('push_to_parent').style.display = parent_enabled ? 'inline-block' : 'none'; document.getElementById('pull_from_parent').style.display = parent_enabled ? 'inline-block' : 'none'; + } else if (message && message.action == 'permissions') { + gPermissions = message.permissions; + let permissions = document.getElementById('permissions_settings'); + if (permissions.firstChild) { + hidePermissions(); + showPermissions(); + } } else if (message && message.action == "ready") { setStatusMessage(null); if (window.location.hash) { diff --git a/core/core.js b/core/core.js index 8b4abb78..3c972118 100644 --- a/core/core.js +++ b/core/core.js @@ -222,11 +222,13 @@ async function getProcessBlob(blobId, key, options) { return process.app.makeFunction(['requestPermission'])(permission).then(function(value) { if (value == 'allow') { storePermission(user, options.packageOwner, options.packageName, permission, true); + process.sendPermissions(); return true; } else if (value == 'allow once') { return true; } else if (value == 'deny') { storePermission(user, options.packageOwner, options.packageName, permission, false); + process.sendPermissions(); throw Error(`Permission denied: ${permission}.`); } else if (value == 'deny once') { throw Error(`Permission denied: ${permission}.`); @@ -322,6 +324,14 @@ async function getProcessBlob(blobId, key, options) { return Object.fromEntries(Object.keys(db).map(x => [x, db[x].bind(db)])); } } + process.sendPermissions = function sendPermissions() { + process.app.send({action: 'permissions', permissions: imports.core.permissionsGranted()}); + } + process.resetPermission = function resetPermission(permission) { + let user = process?.credentials?.session?.name; + storePermission(user, options?.packageOwner, options?.packageName, permission, undefined); + process.sendPermissions(); + } process.task.setImports(imports); process.task.activate(); let source = await getBlobOrContent(blobId); @@ -346,6 +356,7 @@ async function getProcessBlob(blobId, key, options) { resolveReady(process); if (process.app) { process.app.send({action: "ready"}); + process.sendPermissions(); } await process.task.execute({name: appSourceName, source: appSource}); } catch (error) { @@ -759,7 +770,11 @@ function storePermission(user, packageOwner, packageName, permission, allow) { gGlobalSettings.userPermissions[user][packageOwner][packageName] = {}; } if (gGlobalSettings.userPermissions[user][packageOwner][packageName][permission] !== allow) { - gGlobalSettings.userPermissions[user][packageOwner][packageName][permission] = allow; + if (allow === undefined) { + delete gGlobalSettings.userPermissions[user][packageOwner][packageName][permission]; + } else { + gGlobalSettings.userPermissions[user][packageOwner][packageName][permission] = allow; + } setGlobalSettings(gGlobalSettings); } } diff --git a/core/index.html b/core/index.html index 1cf1d5ba..5e74b3b1 100644 --- a/core/index.html +++ b/core/index.html @@ -12,8 +12,10 @@ Tilde Friends apps edit + 🎛️ + diff --git a/core/style.css b/core/style.css index 99fc838d..4983ed23 100644 --- a/core/style.css +++ b/core/style.css @@ -254,7 +254,7 @@ kbd { white-space: nowrap; } -#permissions { +#permissions, #permissions_settings { visibility: hidden; position: absolute; display: block;