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;