2022-06-18 13:39:08 -04:00
|
|
|
import * as app from './app.js';
|
2023-03-22 19:02:36 -04:00
|
|
|
import * as form from './form.js';
|
2023-07-16 17:04:48 -04:00
|
|
|
import * as http from './http.js';
|
2016-03-12 13:50:43 -05:00
|
|
|
|
2023-01-28 17:44:45 -05:00
|
|
|
let gProcesses = {};
|
|
|
|
let gStatsTimer = false;
|
2016-03-12 13:50:43 -05:00
|
|
|
|
2024-02-24 11:09:34 -05:00
|
|
|
const k_content_security_policy =
|
|
|
|
'sandbox allow-downloads allow-top-navigation-by-user-activation';
|
2024-01-28 19:00:20 -05:00
|
|
|
|
2022-11-30 19:26:51 -05:00
|
|
|
const k_global_settings = {
|
|
|
|
index: {
|
|
|
|
type: 'string',
|
|
|
|
default_value: '/~core/apps/',
|
|
|
|
description: 'Default path.',
|
|
|
|
},
|
2023-12-03 12:03:17 -05:00
|
|
|
index_map: {
|
|
|
|
type: 'textarea',
|
|
|
|
default_value: undefined,
|
2024-02-24 11:09:34 -05:00
|
|
|
description:
|
|
|
|
'Mappings from hostname to redirect path, one per line, as in: "www.tildefriends.net=/~core/index/"',
|
2023-12-03 12:03:17 -05:00
|
|
|
},
|
2022-11-30 19:26:51 -05:00
|
|
|
room: {
|
|
|
|
type: 'boolean',
|
|
|
|
default_value: true,
|
2024-08-14 20:02:46 -04:00
|
|
|
description: 'Enable peers to tunnel through this instance as a room.',
|
2022-11-30 19:26:51 -05:00
|
|
|
},
|
2023-01-07 19:25:38 -05:00
|
|
|
room_name: {
|
|
|
|
type: 'string',
|
|
|
|
default_value: 'tilde friends tunnel',
|
|
|
|
description: 'Name of the room.',
|
|
|
|
},
|
2024-08-14 20:02:46 -04:00
|
|
|
replicator: {
|
|
|
|
type: 'boolean',
|
|
|
|
default_value: true,
|
|
|
|
description: 'Enable message and blob replication.',
|
|
|
|
},
|
2022-12-24 14:25:21 -05:00
|
|
|
code_of_conduct: {
|
|
|
|
type: 'textarea',
|
|
|
|
default_value: undefined,
|
|
|
|
description: 'Code of conduct presented at sign-in.',
|
|
|
|
},
|
2023-01-11 18:39:42 -05:00
|
|
|
http_redirect: {
|
|
|
|
type: 'string',
|
|
|
|
default_value: undefined,
|
2024-02-24 11:09:34 -05:00
|
|
|
description:
|
|
|
|
'If connecting by HTTP and HTTPS is configured, Location header prefix (ie, "https://example.com")',
|
2023-01-11 18:39:42 -05:00
|
|
|
},
|
2023-07-16 17:04:48 -04:00
|
|
|
fetch_hosts: {
|
|
|
|
type: 'string',
|
|
|
|
default_value: undefined,
|
2024-02-24 11:09:34 -05:00
|
|
|
description:
|
|
|
|
'Comma-separated list of host names to which HTTP fetch requests are allowed. None if empty.',
|
2023-07-16 17:04:48 -04:00
|
|
|
},
|
2023-07-26 22:51:42 -04:00
|
|
|
blob_fetch_age_seconds: {
|
|
|
|
type: 'integer',
|
2024-02-24 11:09:34 -05:00
|
|
|
default_value:
|
|
|
|
platform() == 'android' || platform() == 'iphone'
|
|
|
|
? 0.5 * 365 * 24 * 60 * 60
|
|
|
|
: undefined,
|
|
|
|
description:
|
|
|
|
'Only blobs mentioned more recently than this age will be automatically fetched.',
|
2023-07-26 22:51:42 -04:00
|
|
|
},
|
|
|
|
blob_expire_age_seconds: {
|
|
|
|
type: 'integer',
|
2024-02-24 11:09:34 -05:00
|
|
|
default_value:
|
|
|
|
platform() == 'android' || platform() == 'iphone'
|
|
|
|
? 1.0 * 365 * 24 * 60 * 60
|
|
|
|
: undefined,
|
2023-07-26 22:51:42 -04:00
|
|
|
description: 'Blobs older than this will be automatically deleted.',
|
|
|
|
},
|
2024-08-07 21:03:39 -04:00
|
|
|
seeds_host: {
|
|
|
|
type: 'string',
|
2024-08-14 21:07:16 -04:00
|
|
|
default_value: 'seeds.tildefriends.net',
|
2024-08-07 21:03:39 -04:00
|
|
|
description: 'Hostname for seed connections.',
|
|
|
|
},
|
2024-08-14 21:07:16 -04:00
|
|
|
peer_exchange: {
|
|
|
|
type: 'boolean',
|
|
|
|
default_value: false,
|
2024-08-28 20:24:26 -04:00
|
|
|
description:
|
|
|
|
'Enable discovery of, sharing of, and connecting to internet peer strangers, including announcing this instance.',
|
2024-08-14 21:07:16 -04:00
|
|
|
},
|
2024-08-21 20:56:21 -04:00
|
|
|
account_registration: {
|
|
|
|
type: 'boolean',
|
|
|
|
default_value: true,
|
|
|
|
description: 'Allow registration of new accounts.',
|
|
|
|
},
|
2022-11-30 19:26:51 -05:00
|
|
|
};
|
|
|
|
|
2023-01-28 17:44:45 -05:00
|
|
|
let kPingInterval = 60 * 1000;
|
2016-03-12 13:50:43 -05:00
|
|
|
|
2024-02-19 13:12:42 -05:00
|
|
|
/**
|
|
|
|
* TODOC
|
2024-02-22 15:23:39 -05:00
|
|
|
* @param {*} out
|
|
|
|
* @param {*} error
|
2024-02-19 13:12:42 -05:00
|
|
|
*/
|
2016-03-12 13:50:43 -05:00
|
|
|
function printError(out, error) {
|
|
|
|
if (error.stackTrace) {
|
2024-02-24 11:09:34 -05:00
|
|
|
out.print(error.fileName + ':' + error.lineNumber + ': ' + error.message);
|
2016-03-12 13:50:43 -05:00
|
|
|
out.print(error.stackTrace);
|
|
|
|
} else {
|
2023-05-27 12:51:56 -04:00
|
|
|
for (let [k, v] of Object.entries(error)) {
|
|
|
|
out.print(k, v);
|
2016-03-12 13:50:43 -05:00
|
|
|
}
|
|
|
|
out.print(error.toString());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-19 13:12:42 -05:00
|
|
|
/**
|
|
|
|
* TODOC
|
2024-02-22 15:23:39 -05:00
|
|
|
* @param {*} handlers
|
|
|
|
* @param {*} argv
|
|
|
|
* @returns
|
2024-02-19 13:12:42 -05:00
|
|
|
*/
|
2021-01-02 13:10:00 -05:00
|
|
|
function invoke(handlers, argv) {
|
2023-01-28 17:44:45 -05:00
|
|
|
let promises = [];
|
2021-01-02 13:10:00 -05:00
|
|
|
if (handlers) {
|
2023-01-28 17:44:45 -05:00
|
|
|
for (let i = 0; i < handlers.length; ++i) {
|
2021-01-02 13:10:00 -05:00
|
|
|
try {
|
|
|
|
promises.push(handlers[i](...argv));
|
|
|
|
} catch (error) {
|
|
|
|
handlers.splice(i, 1);
|
|
|
|
i--;
|
2024-02-24 11:09:34 -05:00
|
|
|
promises.push(
|
|
|
|
new Promise(function (resolve, reject) {
|
|
|
|
reject(error);
|
|
|
|
})
|
|
|
|
);
|
2021-01-02 13:10:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Promise.all(promises);
|
|
|
|
}
|
|
|
|
|
2024-02-19 13:12:42 -05:00
|
|
|
/**
|
|
|
|
* TODOC
|
2024-02-22 15:23:39 -05:00
|
|
|
* @param {*} eventName
|
|
|
|
* @param {*} argv
|
|
|
|
* @returns
|
2024-02-19 13:12:42 -05:00
|
|
|
*/
|
2016-03-12 13:50:43 -05:00
|
|
|
function broadcastEvent(eventName, argv) {
|
2023-01-28 17:44:45 -05:00
|
|
|
let promises = [];
|
2024-01-10 21:11:24 -05:00
|
|
|
for (let process of Object.values(gProcesses)) {
|
2021-01-02 13:10:00 -05:00
|
|
|
if (process.eventHandlers[eventName]) {
|
|
|
|
promises.push(invoke(process.eventHandlers[eventName], argv));
|
|
|
|
}
|
2016-03-12 13:50:43 -05:00
|
|
|
}
|
|
|
|
return Promise.all(promises);
|
|
|
|
}
|
2024-04-13 19:52:40 -04:00
|
|
|
|
2024-02-19 13:12:42 -05:00
|
|
|
/**
|
|
|
|
* TODOC
|
2024-02-22 15:23:39 -05:00
|
|
|
* @param {*} message
|
|
|
|
* @returns
|
2024-02-19 13:12:42 -05:00
|
|
|
*/
|
2016-03-12 13:50:43 -05:00
|
|
|
function broadcast(message) {
|
2023-01-28 17:44:45 -05:00
|
|
|
let sender = this;
|
|
|
|
let promises = [];
|
2024-01-10 21:11:24 -05:00
|
|
|
for (let process of Object.values(gProcesses)) {
|
2024-02-24 11:09:34 -05:00
|
|
|
if (
|
|
|
|
process != sender &&
|
|
|
|
process.packageOwner == sender.packageOwner &&
|
|
|
|
process.packageName == sender.packageName
|
|
|
|
) {
|
2023-01-28 17:44:45 -05:00
|
|
|
let from = getUser(process, sender);
|
2016-03-12 13:50:43 -05:00
|
|
|
promises.push(postMessageInternal(from, process, message));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Promise.all(promises);
|
|
|
|
}
|
|
|
|
|
2024-04-13 19:52:40 -04:00
|
|
|
/**
|
|
|
|
* TODOC
|
|
|
|
* @param {String} eventName
|
|
|
|
* @param {*} argv
|
|
|
|
* @returns
|
|
|
|
*/
|
2024-04-13 20:07:39 -04:00
|
|
|
function broadcastAppEventToUser(
|
|
|
|
user,
|
|
|
|
packageOwner,
|
|
|
|
packageName,
|
|
|
|
eventName,
|
|
|
|
argv
|
|
|
|
) {
|
2024-04-13 19:52:40 -04:00
|
|
|
let promises = [];
|
|
|
|
for (let process of Object.values(gProcesses)) {
|
|
|
|
if (
|
|
|
|
process.credentials?.session?.name === user &&
|
|
|
|
process.packageOwner == packageOwner &&
|
|
|
|
process.packageName == packageName
|
|
|
|
) {
|
|
|
|
if (process.eventHandlers[eventName]) {
|
|
|
|
promises.push(invoke(process.eventHandlers[eventName], argv));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Promise.all(promises);
|
|
|
|
}
|
|
|
|
|
2024-02-19 13:12:42 -05:00
|
|
|
/**
|
|
|
|
* TODOC
|
2024-02-22 15:23:39 -05:00
|
|
|
* @param {*} caller
|
|
|
|
* @param {*} process
|
|
|
|
* @returns
|
2024-02-19 13:12:42 -05:00
|
|
|
*/
|
2016-03-12 13:50:43 -05:00
|
|
|
function getUser(caller, process) {
|
|
|
|
return {
|
2016-03-12 13:55:55 -05:00
|
|
|
key: process.key,
|
2016-03-12 13:50:43 -05:00
|
|
|
packageOwner: process.packageOwner,
|
|
|
|
packageName: process.packageName,
|
|
|
|
credentials: process.credentials,
|
|
|
|
postMessage: postMessageInternal.bind(caller, caller, process),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2024-02-19 13:12:42 -05:00
|
|
|
/**
|
|
|
|
* TODOC
|
2024-02-22 15:23:39 -05:00
|
|
|
* @param {*} user
|
|
|
|
* @param {*} process
|
|
|
|
* @returns
|
2024-02-19 13:12:42 -05:00
|
|
|
*/
|
2024-06-10 15:30:14 -04:00
|
|
|
async function getApps(user, process) {
|
2024-02-24 11:09:34 -05:00
|
|
|
if (
|
|
|
|
process.credentials &&
|
2022-02-13 17:03:12 -05:00
|
|
|
process.credentials.session &&
|
2024-02-24 11:09:34 -05:00
|
|
|
process.credentials.session.name
|
|
|
|
) {
|
2022-02-13 17:03:12 -05:00
|
|
|
if (user && user !== process.credentials.session.name && user !== 'core') {
|
|
|
|
return {};
|
|
|
|
} else if (!user) {
|
|
|
|
user = process.credentials.session.name;
|
2016-03-12 13:50:43 -05:00
|
|
|
}
|
|
|
|
}
|
2022-02-13 17:03:12 -05:00
|
|
|
if (user) {
|
2023-01-28 17:44:45 -05:00
|
|
|
let db = new Database(user);
|
2022-02-13 17:03:12 -05:00
|
|
|
try {
|
2024-06-10 15:30:14 -04:00
|
|
|
let names = JSON.parse(await db.get('apps'));
|
|
|
|
let result = {};
|
|
|
|
for (let name of names) {
|
|
|
|
result[name] = await db.get('path:' + name);
|
|
|
|
}
|
|
|
|
return result;
|
2024-02-24 11:09:34 -05:00
|
|
|
} catch {}
|
2022-02-13 17:03:12 -05:00
|
|
|
}
|
|
|
|
return {};
|
2016-03-12 13:50:43 -05:00
|
|
|
}
|
|
|
|
|
2024-02-19 13:12:42 -05:00
|
|
|
/**
|
|
|
|
* TODOC
|
2024-02-22 15:23:39 -05:00
|
|
|
* @param {*} from
|
|
|
|
* @param {*} to
|
|
|
|
* @param {*} message
|
|
|
|
* @returns
|
2024-02-19 13:12:42 -05:00
|
|
|
*/
|
2016-03-12 13:50:43 -05:00
|
|
|
function postMessageInternal(from, to, message) {
|
2021-01-02 13:10:00 -05:00
|
|
|
if (to.eventHandlers['message']) {
|
|
|
|
return invoke(to.eventHandlers['message'], [getUser(from, from), message]);
|
|
|
|
}
|
2016-03-12 13:50:43 -05:00
|
|
|
}
|
|
|
|
|
2024-02-19 13:12:42 -05:00
|
|
|
/**
|
|
|
|
* TODOC
|
2024-02-22 15:23:39 -05:00
|
|
|
* @param {*} blobId
|
|
|
|
* @param {*} key
|
|
|
|
* @param {*} options
|
|
|
|
* @returns
|
2024-02-19 13:12:42 -05:00
|
|
|
*/
|
2021-01-02 13:10:00 -05:00
|
|
|
async function getProcessBlob(blobId, key, options) {
|
2024-02-19 13:26:15 -05:00
|
|
|
// TODO(tasiaiso): break this down ?
|
2023-01-28 17:44:45 -05:00
|
|
|
let process = gProcesses[key];
|
2024-02-24 11:09:34 -05:00
|
|
|
if (!process && !(options && 'create' in options && !options.create)) {
|
2023-02-16 20:42:56 -05:00
|
|
|
let resolveReady;
|
|
|
|
let rejectReady;
|
2016-03-12 13:50:43 -05:00
|
|
|
try {
|
2024-02-24 11:09:34 -05:00
|
|
|
print('Creating task for ' + blobId + ' ' + key);
|
2016-03-12 13:50:43 -05:00
|
|
|
process = {};
|
|
|
|
process.key = key;
|
|
|
|
process.credentials = options.credentials || {};
|
|
|
|
process.task = new Task();
|
2024-04-13 19:52:40 -04:00
|
|
|
process.packageOwner = options.packageOwner;
|
|
|
|
process.packageName = options.packageName;
|
2016-03-12 13:50:43 -05:00
|
|
|
process.eventHandlers = {};
|
2023-05-19 15:57:40 -04:00
|
|
|
if (!options?.script || options?.script === 'app.js') {
|
|
|
|
process.app = new app.App();
|
|
|
|
}
|
2016-03-12 13:50:43 -05:00
|
|
|
process.lastActive = Date.now();
|
|
|
|
process.lastPing = null;
|
2024-10-16 19:50:31 -04:00
|
|
|
process.timeout = kPingInterval;
|
2024-02-24 11:09:34 -05:00
|
|
|
process.ready = new Promise(function (resolve, reject) {
|
2016-03-12 13:50:43 -05:00
|
|
|
resolveReady = resolve;
|
|
|
|
rejectReady = reject;
|
|
|
|
});
|
|
|
|
gProcesses[key] = process;
|
2024-02-24 11:09:34 -05:00
|
|
|
process.task.onExit = function (exitCode, terminationSignal) {
|
2016-03-12 13:50:43 -05:00
|
|
|
broadcastEvent('onSessionEnd', [getUser(process, process)]);
|
2021-01-02 13:10:00 -05:00
|
|
|
process.task = null;
|
2016-03-12 13:50:43 -05:00
|
|
|
delete gProcesses[key];
|
|
|
|
};
|
2023-01-28 17:44:45 -05:00
|
|
|
let imports = {
|
2024-02-24 11:09:34 -05:00
|
|
|
core: {
|
|
|
|
broadcast: broadcast.bind(process),
|
|
|
|
register: function (eventName, handler) {
|
2016-03-12 13:50:43 -05:00
|
|
|
if (!process.eventHandlers[eventName]) {
|
|
|
|
process.eventHandlers[eventName] = [];
|
|
|
|
}
|
|
|
|
process.eventHandlers[eventName].push(handler);
|
|
|
|
},
|
2024-02-24 11:09:34 -05:00
|
|
|
unregister: function (eventName, handler) {
|
2021-01-02 13:10:00 -05:00
|
|
|
if (process.eventHandlers[eventName]) {
|
2016-04-03 15:31:03 -04:00
|
|
|
let index = process.eventHandlers[eventName].indexOf(handler);
|
|
|
|
if (index != -1) {
|
|
|
|
process.eventHandlers[eventName].splice(index, 1);
|
|
|
|
}
|
|
|
|
if (process.eventHandlers[eventName].length == 0) {
|
|
|
|
delete process.eventHandlers[eventName];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
2024-02-24 11:09:34 -05:00
|
|
|
user: getUser(process, process),
|
2024-06-10 15:30:14 -04:00
|
|
|
users: async function () {
|
2022-08-03 20:07:12 -04:00
|
|
|
try {
|
2024-06-10 15:30:14 -04:00
|
|
|
return JSON.parse(await new Database('auth').get('users'));
|
2022-08-03 20:07:12 -04:00
|
|
|
} catch {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
},
|
2024-10-16 18:11:08 -04:00
|
|
|
permissionsGranted: async function () {
|
2022-08-13 21:46:11 -04:00
|
|
|
let user = process?.credentials?.session?.name;
|
2024-10-16 18:11:08 -04:00
|
|
|
let settings = await loadSettings();
|
2024-02-24 11:09:34 -05:00
|
|
|
if (
|
|
|
|
user &&
|
2022-08-13 21:46:11 -04:00
|
|
|
options?.packageOwner &&
|
|
|
|
options?.packageName &&
|
2024-10-16 18:11:08 -04:00
|
|
|
settings.userPermissions &&
|
|
|
|
settings.userPermissions[user] &&
|
|
|
|
settings.userPermissions[user][options.packageOwner]
|
2024-02-24 11:09:34 -05:00
|
|
|
) {
|
2024-10-23 15:38:49 -04:00
|
|
|
return settings.userPermissions[user][options.packageOwner][
|
|
|
|
options.packageName
|
|
|
|
];
|
2022-08-13 21:46:11 -04:00
|
|
|
}
|
|
|
|
},
|
2024-10-16 18:11:08 -04:00
|
|
|
allPermissionsGranted: async function () {
|
2022-08-13 21:46:11 -04:00
|
|
|
let user = process?.credentials?.session?.name;
|
2024-10-16 18:11:08 -04:00
|
|
|
let settings = await loadSettings();
|
2024-02-24 11:09:34 -05:00
|
|
|
if (
|
|
|
|
user &&
|
2022-08-13 21:46:11 -04:00
|
|
|
options?.packageOwner &&
|
|
|
|
options?.packageName &&
|
2024-10-16 18:11:08 -04:00
|
|
|
settings.userPermissions &&
|
|
|
|
settings.userPermissions[user]
|
2024-02-24 11:09:34 -05:00
|
|
|
) {
|
2024-10-16 18:11:08 -04:00
|
|
|
return settings.userPermissions[user];
|
2022-08-13 21:46:11 -04:00
|
|
|
}
|
|
|
|
},
|
2024-10-16 18:11:08 -04:00
|
|
|
permissionsForUser: async function (user) {
|
|
|
|
let settings = await loadSettings();
|
|
|
|
return settings?.permissions?.[user] ?? [];
|
2022-08-13 14:06:30 -04:00
|
|
|
},
|
2024-02-24 11:09:34 -05:00
|
|
|
apps: (user) => getApps(user, process),
|
|
|
|
getSockets: getSockets,
|
2024-10-16 18:11:08 -04:00
|
|
|
permissionTest: async function (permission) {
|
2022-07-26 20:27:10 -04:00
|
|
|
let user = process?.credentials?.session?.name;
|
2024-10-16 18:11:08 -04:00
|
|
|
let settings = await loadSettings();
|
2022-07-26 20:27:10 -04:00
|
|
|
if (!user || !options?.packageOwner || !options?.packageName) {
|
2022-08-13 21:46:11 -04:00
|
|
|
return;
|
2024-02-24 11:09:34 -05:00
|
|
|
} else if (
|
2024-10-16 18:11:08 -04:00
|
|
|
settings.userPermissions &&
|
|
|
|
settings.userPermissions[user] &&
|
|
|
|
settings.userPermissions[user][options.packageOwner] &&
|
|
|
|
settings.userPermissions[user][options.packageOwner][
|
2024-02-24 11:09:34 -05:00
|
|
|
options.packageName
|
|
|
|
] &&
|
2024-10-16 18:11:08 -04:00
|
|
|
settings.userPermissions[user][options.packageOwner][
|
2024-02-24 11:09:34 -05:00
|
|
|
options.packageName
|
|
|
|
][permission] !== undefined
|
|
|
|
) {
|
|
|
|
if (
|
2024-10-16 18:11:08 -04:00
|
|
|
settings.userPermissions[user][options.packageOwner][
|
2024-02-24 11:09:34 -05:00
|
|
|
options.packageName
|
|
|
|
][permission]
|
|
|
|
) {
|
2022-08-13 21:46:11 -04:00
|
|
|
return true;
|
2022-07-26 20:27:10 -04:00
|
|
|
} else {
|
2022-08-14 13:34:27 -04:00
|
|
|
throw Error(`Permission denied: ${permission}.`);
|
2022-07-26 20:27:10 -04:00
|
|
|
}
|
2023-05-19 15:57:40 -04:00
|
|
|
} else if (process.app) {
|
2024-02-24 11:09:34 -05:00
|
|
|
return process.app
|
|
|
|
.makeFunction(['requestPermission'])(permission)
|
2024-10-16 20:36:53 -04:00
|
|
|
.then(async function (value) {
|
2024-02-24 11:09:34 -05:00
|
|
|
if (value == 'allow') {
|
2024-10-16 20:36:53 -04:00
|
|
|
await ssb.setUserPermission(
|
2024-02-24 11:09:34 -05:00
|
|
|
user,
|
|
|
|
options.packageOwner,
|
|
|
|
options.packageName,
|
|
|
|
permission,
|
|
|
|
true
|
|
|
|
);
|
|
|
|
process.sendPermissions();
|
|
|
|
return true;
|
|
|
|
} else if (value == 'allow once') {
|
|
|
|
return true;
|
|
|
|
} else if (value == 'deny') {
|
2024-10-16 20:36:53 -04:00
|
|
|
await ssb.setUserPermission(
|
2024-02-24 11:09:34 -05:00
|
|
|
user,
|
|
|
|
options.packageOwner,
|
|
|
|
options.packageName,
|
|
|
|
permission,
|
|
|
|
false
|
|
|
|
);
|
|
|
|
process.sendPermissions();
|
|
|
|
throw Error(`Permission denied: ${permission}.`);
|
|
|
|
} else if (value == 'deny once') {
|
|
|
|
throw Error(`Permission denied: ${permission}.`);
|
|
|
|
}
|
2022-08-14 13:34:27 -04:00
|
|
|
throw Error(`Permission denied: ${permission}.`);
|
2024-02-24 11:09:34 -05:00
|
|
|
});
|
2023-05-19 15:57:40 -04:00
|
|
|
} else {
|
|
|
|
throw Error(`Permission denied: ${permission}.`);
|
2022-07-26 20:27:10 -04:00
|
|
|
}
|
|
|
|
},
|
2024-01-10 19:50:12 -05:00
|
|
|
app: {
|
|
|
|
owner: options?.packageOwner,
|
|
|
|
name: options?.packageName,
|
|
|
|
},
|
2023-07-30 20:26:09 -04:00
|
|
|
url: options?.url,
|
2024-02-24 11:09:34 -05:00
|
|
|
},
|
2021-01-02 13:10:00 -05:00
|
|
|
};
|
2024-04-13 20:07:39 -04:00
|
|
|
process.sendIdentities = async function () {
|
2024-04-17 20:56:33 -04:00
|
|
|
process.app.send(
|
|
|
|
Object.assign(
|
|
|
|
{
|
|
|
|
action: 'identities',
|
|
|
|
},
|
2024-05-05 13:48:22 -04:00
|
|
|
await ssb.getIdentityInfo(
|
2024-04-17 20:56:33 -04:00
|
|
|
process?.credentials?.session?.name,
|
|
|
|
options?.packageOwner,
|
|
|
|
options?.packageName
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
2024-04-13 13:22:59 -04:00
|
|
|
};
|
2024-04-13 20:07:39 -04:00
|
|
|
process.setActiveIdentity = async function (identity) {
|
|
|
|
if (
|
|
|
|
process?.credentials?.session?.name &&
|
|
|
|
options.packageOwner &&
|
|
|
|
options.packageName
|
|
|
|
) {
|
|
|
|
await new Database(process?.credentials?.session?.name).set(
|
|
|
|
`id:${options.packageOwner}:${options.packageName}`,
|
|
|
|
identity
|
|
|
|
);
|
2024-04-13 13:22:59 -04:00
|
|
|
}
|
|
|
|
process.sendIdentities();
|
2024-04-13 20:07:39 -04:00
|
|
|
broadcastAppEventToUser(
|
|
|
|
process?.credentials?.session?.name,
|
|
|
|
options.packageOwner,
|
|
|
|
options.packageName,
|
|
|
|
'setActiveIdentity',
|
|
|
|
[identity]
|
|
|
|
);
|
2024-04-13 13:22:59 -04:00
|
|
|
};
|
2024-04-13 20:07:39 -04:00
|
|
|
process.createIdentity = async function () {
|
2024-04-13 13:22:59 -04:00
|
|
|
if (
|
|
|
|
process.credentials &&
|
|
|
|
process.credentials.session &&
|
2024-05-14 12:41:17 -04:00
|
|
|
process.credentials.session.name &&
|
|
|
|
process.credentials.session.name !== 'guest'
|
2024-04-13 13:22:59 -04:00
|
|
|
) {
|
2024-06-12 20:47:48 -04:00
|
|
|
let id = await ssb.createIdentity(process.credentials.session.name);
|
2024-04-13 13:22:59 -04:00
|
|
|
await process.sendIdentities();
|
2024-04-13 20:32:17 -04:00
|
|
|
broadcastAppEventToUser(
|
|
|
|
process?.credentials?.session?.name,
|
|
|
|
options.packageOwner,
|
|
|
|
options.packageName,
|
|
|
|
'setActiveIdentity',
|
|
|
|
[
|
2024-05-05 12:55:32 -04:00
|
|
|
await ssb.getActiveIdentity(
|
2024-04-13 20:32:17 -04:00
|
|
|
process.credentials?.session?.name,
|
|
|
|
options.packageOwner,
|
|
|
|
options.packageName
|
2024-04-17 20:56:33 -04:00
|
|
|
),
|
2024-04-13 20:32:17 -04:00
|
|
|
]
|
|
|
|
);
|
2024-04-13 13:22:59 -04:00
|
|
|
return id;
|
2024-05-14 12:41:17 -04:00
|
|
|
} else {
|
|
|
|
throw new Error('Must be signed-in to create an account.');
|
2024-04-13 13:22:59 -04:00
|
|
|
}
|
2024-04-13 20:07:39 -04:00
|
|
|
};
|
2022-08-03 20:57:56 -04:00
|
|
|
if (process.credentials?.permissions?.administration) {
|
2024-10-16 18:11:08 -04:00
|
|
|
imports.core.globalSettingsDescriptions = async function () {
|
2022-11-30 19:26:51 -05:00
|
|
|
let settings = Object.assign({}, k_global_settings);
|
2024-10-16 18:11:08 -04:00
|
|
|
for (let [key, value] of Object.entries(await loadSettings())) {
|
2022-11-30 19:26:51 -05:00
|
|
|
if (settings[key]) {
|
|
|
|
settings[key].value = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return settings;
|
|
|
|
};
|
2024-10-16 18:11:08 -04:00
|
|
|
imports.core.globalSettingsGet = async function (key) {
|
|
|
|
let settings = await loadSettings();
|
|
|
|
return settings?.[key];
|
2022-08-16 20:29:57 -04:00
|
|
|
};
|
2024-08-28 19:39:05 -04:00
|
|
|
imports.core.globalSettingsSet = async function (key, value) {
|
2022-08-16 20:29:57 -04:00
|
|
|
print('Setting', key, value);
|
2024-10-16 18:11:08 -04:00
|
|
|
let settings = await loadSettings();
|
|
|
|
settings[key] = value;
|
2024-10-16 21:02:48 -04:00
|
|
|
await new Database('core').set('settings', JSON.stringify(settings));
|
2022-08-16 20:29:57 -04:00
|
|
|
print('Done.');
|
|
|
|
};
|
2024-06-10 15:30:14 -04:00
|
|
|
imports.core.deleteUser = async function (user) {
|
2024-06-20 12:36:21 -04:00
|
|
|
await imports.core.permissionTest('delete_user');
|
2024-06-10 15:30:14 -04:00
|
|
|
let db = new Database('auth');
|
|
|
|
db.remove('user:' + user);
|
|
|
|
let users = new Set();
|
|
|
|
let users_original = await db.get('users');
|
|
|
|
try {
|
|
|
|
users = new Set(JSON.parse(users_original));
|
|
|
|
} catch {}
|
|
|
|
users.delete(user);
|
|
|
|
users = JSON.stringify([...users].sort());
|
|
|
|
if (users !== users_original) {
|
|
|
|
await db.set('users', users);
|
|
|
|
}
|
2022-08-16 20:29:57 -04:00
|
|
|
};
|
2022-08-03 20:57:56 -04:00
|
|
|
}
|
2021-01-02 13:10:00 -05:00
|
|
|
if (options.api) {
|
|
|
|
imports.app = {};
|
|
|
|
for (let i in options.api) {
|
|
|
|
let api = options.api[i];
|
|
|
|
imports.app[api[0]] = process.app.makeFunction(api);
|
2016-03-12 13:50:43 -05:00
|
|
|
}
|
|
|
|
}
|
2023-05-17 16:22:13 -04:00
|
|
|
for (let [name, f] of Object.entries(options?.imports || {})) {
|
|
|
|
imports[name] = f;
|
|
|
|
}
|
2024-02-24 11:09:34 -05:00
|
|
|
process.task.onPrint = function (args) {
|
2023-05-17 16:22:13 -04:00
|
|
|
if (imports.app) {
|
|
|
|
imports.app.print(...args);
|
|
|
|
}
|
2022-02-13 17:39:22 -05:00
|
|
|
};
|
2024-02-24 11:09:34 -05:00
|
|
|
process.task.onError = function (error) {
|
2021-01-02 13:10:00 -05:00
|
|
|
try {
|
2023-05-19 15:57:40 -04:00
|
|
|
if (process.app) {
|
|
|
|
process.app.makeFunction(['error'])(error);
|
|
|
|
} else {
|
2023-05-27 12:51:56 -04:00
|
|
|
printError({print: print}, error);
|
2023-05-19 15:57:40 -04:00
|
|
|
}
|
|
|
|
} catch (e) {
|
2023-05-27 12:51:56 -04:00
|
|
|
printError({print: print}, error);
|
2016-04-16 17:30:52 -04:00
|
|
|
}
|
2021-01-02 13:10:00 -05:00
|
|
|
};
|
2024-02-24 11:09:34 -05:00
|
|
|
imports.ssb = Object.fromEntries(
|
|
|
|
Object.keys(ssb).map((key) => [key, ssb[key].bind(ssb)])
|
|
|
|
);
|
2024-03-07 21:03:14 -05:00
|
|
|
imports.ssb.port = tildefriends.ssb_port;
|
2024-04-13 13:22:59 -04:00
|
|
|
imports.ssb.createIdentity = () => process.createIdentity();
|
2024-02-24 11:09:34 -05:00
|
|
|
imports.ssb.addIdentity = function (id) {
|
|
|
|
if (
|
|
|
|
process.credentials &&
|
2024-01-03 20:17:30 -05:00
|
|
|
process.credentials.session &&
|
2024-02-24 11:09:34 -05:00
|
|
|
process.credentials.session.name
|
|
|
|
) {
|
|
|
|
return Promise.resolve(
|
|
|
|
imports.core.permissionTest('ssb_id_add')
|
|
|
|
).then(function () {
|
2024-01-03 20:17:30 -05:00
|
|
|
return ssb.addIdentity(process.credentials.session.name, id);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
2024-02-24 11:09:34 -05:00
|
|
|
imports.ssb.deleteIdentity = function (id) {
|
|
|
|
if (
|
|
|
|
process.credentials &&
|
2024-01-06 14:22:49 -05:00
|
|
|
process.credentials.session &&
|
2024-02-24 11:09:34 -05:00
|
|
|
process.credentials.session.name
|
|
|
|
) {
|
|
|
|
return Promise.resolve(
|
|
|
|
imports.core.permissionTest('ssb_id_delete')
|
|
|
|
).then(function () {
|
2024-01-06 14:22:49 -05:00
|
|
|
return ssb.deleteIdentity(process.credentials.session.name, id);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
2024-04-13 20:07:39 -04:00
|
|
|
imports.ssb.setActiveIdentity = (id) => process.setActiveIdentity(id);
|
|
|
|
imports.ssb.getActiveIdentity = () =>
|
2024-05-05 12:55:32 -04:00
|
|
|
ssb.getActiveIdentity(
|
2024-04-13 20:07:39 -04:00
|
|
|
process.credentials?.session?.name,
|
|
|
|
options.packageOwner,
|
|
|
|
options.packageName
|
|
|
|
);
|
2024-02-24 11:09:34 -05:00
|
|
|
imports.ssb.getOwnerIdentities = function () {
|
2023-11-01 19:10:29 -04:00
|
|
|
if (options.packageOwner) {
|
|
|
|
return ssb.getIdentities(options.packageOwner);
|
|
|
|
}
|
|
|
|
};
|
2024-02-24 11:09:34 -05:00
|
|
|
imports.ssb.getIdentities = function () {
|
|
|
|
if (
|
|
|
|
process.credentials &&
|
2022-07-13 21:01:14 -04:00
|
|
|
process.credentials.session &&
|
2024-02-24 11:09:34 -05:00
|
|
|
process.credentials.session.name
|
|
|
|
) {
|
2022-07-13 21:01:14 -04:00
|
|
|
return ssb.getIdentities(process.credentials.session.name);
|
|
|
|
}
|
|
|
|
};
|
2024-02-24 11:09:34 -05:00
|
|
|
imports.ssb.getPrivateKey = function (id) {
|
|
|
|
if (
|
|
|
|
process.credentials &&
|
2024-01-03 19:21:15 -05:00
|
|
|
process.credentials.session &&
|
2024-02-24 11:09:34 -05:00
|
|
|
process.credentials.session.name
|
|
|
|
) {
|
|
|
|
return Promise.resolve(
|
|
|
|
imports.core.permissionTest('ssb_id_export')
|
|
|
|
).then(function () {
|
2024-01-03 19:21:15 -05:00
|
|
|
return ssb.getPrivateKey(process.credentials.session.name, id);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
};
|
2024-02-24 11:09:34 -05:00
|
|
|
imports.ssb.appendMessageWithIdentity = function (id, message) {
|
|
|
|
if (
|
|
|
|
process.credentials &&
|
2022-07-31 15:01:08 -04:00
|
|
|
process.credentials.session &&
|
2024-02-24 11:09:34 -05:00
|
|
|
process.credentials.session.name
|
|
|
|
) {
|
|
|
|
return Promise.resolve(
|
|
|
|
imports.core.permissionTest('ssb_append')
|
|
|
|
).then(function () {
|
|
|
|
return ssb.appendMessageWithIdentity(
|
|
|
|
process.credentials.session.name,
|
|
|
|
id,
|
|
|
|
message
|
|
|
|
);
|
2022-08-13 21:46:11 -04:00
|
|
|
});
|
2022-07-31 15:01:08 -04:00
|
|
|
}
|
|
|
|
};
|
2024-02-24 11:09:34 -05:00
|
|
|
imports.ssb.privateMessageEncrypt = function (id, recipients, message) {
|
|
|
|
if (
|
|
|
|
process.credentials &&
|
2023-02-26 14:51:54 -05:00
|
|
|
process.credentials.session &&
|
2024-02-24 11:09:34 -05:00
|
|
|
process.credentials.session.name
|
|
|
|
) {
|
|
|
|
return ssb.privateMessageEncrypt(
|
|
|
|
process.credentials.session.name,
|
|
|
|
id,
|
|
|
|
recipients,
|
|
|
|
message
|
|
|
|
);
|
2023-02-26 14:51:54 -05:00
|
|
|
}
|
|
|
|
};
|
2024-02-24 11:09:34 -05:00
|
|
|
imports.ssb.privateMessageDecrypt = function (id, message) {
|
|
|
|
if (
|
|
|
|
process.credentials &&
|
2023-02-26 14:51:54 -05:00
|
|
|
process.credentials.session &&
|
2024-02-24 11:09:34 -05:00
|
|
|
process.credentials.session.name
|
|
|
|
) {
|
|
|
|
return ssb.privateMessageDecrypt(
|
|
|
|
process.credentials.session.name,
|
|
|
|
id,
|
|
|
|
message
|
|
|
|
);
|
2023-02-26 14:51:54 -05:00
|
|
|
}
|
|
|
|
};
|
2024-02-24 11:09:34 -05:00
|
|
|
imports.ssb.setServerFollowingMe = function (id, following) {
|
|
|
|
if (
|
|
|
|
process.credentials &&
|
2023-10-20 10:37:24 -04:00
|
|
|
process.credentials.session &&
|
2024-02-24 11:09:34 -05:00
|
|
|
process.credentials.session.name
|
|
|
|
) {
|
|
|
|
return ssb.setServerFollowingMe(
|
|
|
|
process.credentials.session.name,
|
|
|
|
id,
|
|
|
|
following
|
|
|
|
);
|
2023-10-20 10:37:24 -04:00
|
|
|
}
|
|
|
|
};
|
2024-10-13 14:40:14 -04:00
|
|
|
imports.ssb.swapWithServerIdentity = function (id) {
|
|
|
|
if (
|
|
|
|
process.credentials &&
|
|
|
|
process.credentials.session &&
|
|
|
|
process.credentials.session.name
|
|
|
|
) {
|
|
|
|
return ssb.swapWithServerIdentity(
|
|
|
|
process.credentials.session.name,
|
|
|
|
id
|
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
2024-05-22 18:51:21 -04:00
|
|
|
imports.ssb.addEventListener = undefined;
|
|
|
|
imports.ssb.removeEventListener = undefined;
|
2024-05-05 13:48:22 -04:00
|
|
|
imports.ssb.getIdentityInfo = undefined;
|
2024-10-16 18:11:08 -04:00
|
|
|
imports.fetch = async function (url, options) {
|
|
|
|
let settings = await loadSettings();
|
|
|
|
return http.fetch(url, options, settings?.fetch_hosts);
|
2024-02-24 11:09:34 -05:00
|
|
|
};
|
2022-07-31 15:45:28 -04:00
|
|
|
|
2024-02-24 11:09:34 -05:00
|
|
|
if (
|
|
|
|
process.credentials &&
|
2021-01-02 13:10:00 -05:00
|
|
|
process.credentials.session &&
|
2024-02-24 11:09:34 -05:00
|
|
|
process.credentials.session.name
|
|
|
|
) {
|
|
|
|
imports.database = function (key) {
|
2023-01-28 17:44:45 -05:00
|
|
|
let db = new Database(process.credentials.session.name + ':' + key);
|
2024-02-24 11:09:34 -05:00
|
|
|
return Object.fromEntries(
|
|
|
|
Object.keys(db).map((x) => [x, db[x].bind(db)])
|
|
|
|
);
|
2021-01-02 13:10:00 -05:00
|
|
|
};
|
2024-02-24 11:09:34 -05:00
|
|
|
imports.my_shared_database = function (packageName, key) {
|
|
|
|
let db = new Database(
|
|
|
|
':shared:' +
|
|
|
|
process.credentials.session.name +
|
|
|
|
':' +
|
|
|
|
packageName +
|
|
|
|
':' +
|
|
|
|
key
|
|
|
|
);
|
|
|
|
return Object.fromEntries(
|
|
|
|
Object.keys(db).map((x) => [x, db[x].bind(db)])
|
|
|
|
);
|
2022-05-25 19:45:52 -04:00
|
|
|
};
|
2024-10-29 20:19:50 -04:00
|
|
|
imports.databases = async function () {
|
2024-02-24 11:09:34 -05:00
|
|
|
return [].concat(
|
2024-10-29 20:19:50 -04:00
|
|
|
await databases.list(
|
2024-02-24 11:09:34 -05:00
|
|
|
':shared:' + process.credentials.session.name + ':%'
|
|
|
|
),
|
2024-10-29 20:19:50 -04:00
|
|
|
await databases.list(process.credentials.session.name + ':%')
|
2024-02-24 11:09:34 -05:00
|
|
|
);
|
2022-05-25 19:45:52 -04:00
|
|
|
};
|
2016-04-09 11:24:48 -04:00
|
|
|
}
|
2022-03-15 20:23:14 -04:00
|
|
|
if (options.packageOwner && options.packageName) {
|
2024-02-24 11:09:34 -05:00
|
|
|
imports.shared_database = function (key) {
|
|
|
|
let db = new Database(
|
|
|
|
':shared:' +
|
|
|
|
options.packageOwner +
|
|
|
|
':' +
|
|
|
|
options.packageName +
|
|
|
|
':' +
|
|
|
|
key
|
|
|
|
);
|
|
|
|
return Object.fromEntries(
|
|
|
|
Object.keys(db).map((x) => [x, db[x].bind(db)])
|
|
|
|
);
|
|
|
|
};
|
2022-03-15 20:23:14 -04:00
|
|
|
}
|
2024-10-16 18:11:08 -04:00
|
|
|
process.sendPermissions = async function sendPermissions() {
|
2024-02-24 11:09:34 -05:00
|
|
|
process.app.send({
|
|
|
|
action: 'permissions',
|
2024-10-16 18:11:08 -04:00
|
|
|
permissions: await imports.core.permissionsGranted(),
|
2024-02-24 11:09:34 -05:00
|
|
|
});
|
|
|
|
};
|
2024-10-16 18:11:08 -04:00
|
|
|
process.resetPermission = async function resetPermission(permission) {
|
2022-08-14 14:24:41 -04:00
|
|
|
let user = process?.credentials?.session?.name;
|
2024-10-16 20:36:53 -04:00
|
|
|
await ssb.setUserPermission(
|
2024-02-24 11:09:34 -05:00
|
|
|
user,
|
|
|
|
options?.packageOwner,
|
|
|
|
options?.packageName,
|
|
|
|
permission,
|
|
|
|
undefined
|
|
|
|
);
|
2024-10-16 18:11:08 -04:00
|
|
|
return process.sendPermissions();
|
2024-02-24 11:09:34 -05:00
|
|
|
};
|
2016-03-12 13:50:43 -05:00
|
|
|
process.task.setImports(imports);
|
|
|
|
process.task.activate();
|
2024-06-16 16:02:39 -04:00
|
|
|
let source = await ssb.blobGet(blobId);
|
2023-01-28 17:44:45 -05:00
|
|
|
let appSourceName = blobId;
|
|
|
|
let appSource = utf8Decode(source);
|
2021-01-02 13:10:00 -05:00
|
|
|
try {
|
2023-01-28 17:44:45 -05:00
|
|
|
let appObject = JSON.parse(appSource);
|
2024-02-24 11:09:34 -05:00
|
|
|
if (appObject.type == 'tildefriends-app') {
|
2023-05-17 16:22:13 -04:00
|
|
|
appSourceName = options?.script ?? 'app.js';
|
2023-01-28 17:44:45 -05:00
|
|
|
let id = appObject.files[appSourceName];
|
2024-06-16 16:02:39 -04:00
|
|
|
let blob = await ssb.blobGet(id);
|
2021-01-02 13:10:00 -05:00
|
|
|
appSource = utf8Decode(blob);
|
2024-02-24 11:09:34 -05:00
|
|
|
await process.task.loadFile([
|
|
|
|
'/tfrpc.js',
|
|
|
|
await File.readFile('core/tfrpc.js'),
|
|
|
|
]);
|
|
|
|
await Promise.all(
|
|
|
|
Object.keys(appObject.files).map(async function (f) {
|
|
|
|
await process.task.loadFile([
|
|
|
|
f,
|
2024-06-16 16:02:39 -04:00
|
|
|
await ssb.blobGet(appObject.files[f]),
|
2024-02-24 11:09:34 -05:00
|
|
|
]);
|
|
|
|
})
|
|
|
|
);
|
2021-01-02 13:10:00 -05:00
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
printError({print: print}, e);
|
|
|
|
}
|
2017-05-23 13:47:48 -04:00
|
|
|
broadcastEvent('onSessionBegin', [getUser(process, process)]);
|
2021-01-02 13:10:00 -05:00
|
|
|
if (process.app) {
|
2024-02-24 11:09:34 -05:00
|
|
|
process.app.send({action: 'ready', version: version()});
|
2024-10-16 18:11:08 -04:00
|
|
|
await process.sendPermissions();
|
2017-05-23 13:47:48 -04:00
|
|
|
}
|
2022-01-30 16:09:32 -05:00
|
|
|
await process.task.execute({name: appSourceName, source: appSource});
|
2023-05-27 12:51:56 -04:00
|
|
|
resolveReady(process);
|
2024-07-24 12:15:05 -04:00
|
|
|
if (!gStatsTimer) {
|
|
|
|
gStatsTimer = true;
|
|
|
|
sendStats();
|
|
|
|
}
|
2016-03-12 13:50:43 -05:00
|
|
|
} catch (error) {
|
2023-05-27 12:51:56 -04:00
|
|
|
if (process.app) {
|
|
|
|
if (process?.task?.onError) {
|
|
|
|
process.task.onError(error);
|
|
|
|
} else {
|
|
|
|
printError({print: print}, error);
|
|
|
|
}
|
2022-01-02 21:25:11 -05:00
|
|
|
} else {
|
|
|
|
printError({print: print}, error);
|
|
|
|
}
|
2023-05-27 12:51:56 -04:00
|
|
|
rejectReady(error);
|
2016-03-12 13:50:43 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return process;
|
|
|
|
}
|
|
|
|
|
2024-02-19 13:12:42 -05:00
|
|
|
/**
|
|
|
|
* TODOC
|
2024-02-22 15:23:39 -05:00
|
|
|
* @param {*} response
|
|
|
|
* @param {*} data
|
|
|
|
* @param {*} type
|
|
|
|
* @param {*} headers
|
|
|
|
* @param {*} status_code
|
2024-02-19 13:12:42 -05:00
|
|
|
*/
|
2023-07-16 17:04:48 -04:00
|
|
|
function sendData(response, data, type, headers, status_code) {
|
2023-05-14 15:31:45 -04:00
|
|
|
if (data) {
|
2024-02-24 11:09:34 -05:00
|
|
|
response.writeHead(
|
|
|
|
status_code ?? 200,
|
|
|
|
Object.assign(
|
|
|
|
{
|
|
|
|
'Content-Type':
|
2024-05-15 19:25:48 -04:00
|
|
|
type ||
|
|
|
|
httpd.mime_type_from_magic_bytes(data) ||
|
|
|
|
'application/binary',
|
2024-02-24 11:09:34 -05:00
|
|
|
'Content-Length': data.byteLength,
|
|
|
|
},
|
|
|
|
headers || {}
|
|
|
|
)
|
|
|
|
);
|
2023-05-14 14:47:19 -04:00
|
|
|
response.end(data);
|
2021-01-02 13:10:00 -05:00
|
|
|
} else {
|
2024-02-24 11:09:34 -05:00
|
|
|
response.writeHead(
|
|
|
|
status_code ?? 404,
|
|
|
|
Object.assign(
|
|
|
|
{
|
|
|
|
'Content-Type': 'text/plain; charset=utf-8',
|
|
|
|
'Content-Length': 'File not found'.length,
|
|
|
|
},
|
|
|
|
headers || {}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
response.end('File not found');
|
2021-01-02 13:10:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-05-22 18:51:21 -04:00
|
|
|
ssb.addEventListener('message', function () {
|
|
|
|
broadcastEvent('onMessage', [...arguments]);
|
|
|
|
});
|
|
|
|
|
2024-02-24 11:09:34 -05:00
|
|
|
ssb.addEventListener('broadcasts', function () {
|
2021-01-02 13:10:00 -05:00
|
|
|
broadcastEvent('onBroadcastsChanged', []);
|
2021-11-07 17:28:58 -05:00
|
|
|
});
|
2021-01-02 13:10:00 -05:00
|
|
|
|
2024-02-24 11:09:34 -05:00
|
|
|
ssb.addEventListener('connections', function () {
|
2021-01-02 13:10:00 -05:00
|
|
|
broadcastEvent('onConnectionsChanged', []);
|
2021-11-07 17:28:58 -05:00
|
|
|
});
|
2021-01-02 13:10:00 -05:00
|
|
|
|
2024-02-19 13:12:42 -05:00
|
|
|
/**
|
|
|
|
* TODOC
|
|
|
|
*/
|
2021-10-05 21:25:33 -04:00
|
|
|
async function loadSettings() {
|
2023-02-01 18:40:21 -05:00
|
|
|
let data = {};
|
2021-10-05 21:25:33 -04:00
|
|
|
try {
|
2024-06-10 15:30:14 -04:00
|
|
|
let settings = await new Database('core').get('settings');
|
2022-01-17 21:50:46 -05:00
|
|
|
if (settings) {
|
|
|
|
data = JSON.parse(settings);
|
2017-01-29 07:30:02 -05:00
|
|
|
}
|
2021-10-05 21:25:33 -04:00
|
|
|
} catch (error) {
|
2024-02-24 11:09:34 -05:00
|
|
|
print('Settings not found in database:', error);
|
2022-01-17 21:50:46 -05:00
|
|
|
}
|
2023-03-10 21:37:27 -05:00
|
|
|
for (let [key, value] of Object.entries(k_global_settings)) {
|
|
|
|
if (data[key] === undefined) {
|
|
|
|
data[key] = value.default_value;
|
|
|
|
}
|
|
|
|
}
|
2024-10-16 18:11:08 -04:00
|
|
|
return data;
|
2021-10-05 21:25:33 -04:00
|
|
|
}
|
|
|
|
|
2024-02-19 13:12:42 -05:00
|
|
|
/**
|
|
|
|
* TODOC
|
|
|
|
*/
|
2022-01-20 21:53:15 -05:00
|
|
|
function sendStats() {
|
2024-02-24 11:09:34 -05:00
|
|
|
let apps = Object.values(gProcesses)
|
2024-07-24 12:15:05 -04:00
|
|
|
.filter((process) => process.app)
|
2024-02-24 11:09:34 -05:00
|
|
|
.map((process) => process.app);
|
2023-01-27 19:14:56 -05:00
|
|
|
if (apps.length) {
|
|
|
|
let stats = getStats();
|
|
|
|
for (let app of apps) {
|
|
|
|
app.send({action: 'stats', stats: stats});
|
2022-01-20 21:53:15 -05:00
|
|
|
}
|
2022-02-26 16:17:15 -05:00
|
|
|
setTimeout(sendStats, 1000);
|
|
|
|
} else {
|
|
|
|
gStatsTimer = false;
|
|
|
|
}
|
2022-01-20 21:53:15 -05:00
|
|
|
}
|
|
|
|
|
2024-02-19 13:12:42 -05:00
|
|
|
/**
|
|
|
|
* TODOC
|
|
|
|
*/
|
2024-02-24 11:09:34 -05:00
|
|
|
loadSettings()
|
2024-10-16 18:11:08 -04:00
|
|
|
.then(function (settings) {
|
|
|
|
if (tildefriends.https_port && settings.http_redirect) {
|
|
|
|
httpd.set_http_redirect(settings.http_redirect);
|
2024-02-24 11:09:34 -05:00
|
|
|
}
|
|
|
|
httpd.all('/app/socket', app.socket);
|
|
|
|
let port = httpd.start(tildefriends.http_port);
|
|
|
|
if (tildefriends.args.out_http_port_file) {
|
|
|
|
print('Writing the port file.');
|
|
|
|
File.writeFile(
|
|
|
|
tildefriends.args.out_http_port_file,
|
|
|
|
port.toString() + '\n'
|
|
|
|
)
|
|
|
|
.then(function (r) {
|
|
|
|
print(
|
|
|
|
'Wrote the port file:',
|
|
|
|
tildefriends.args.out_http_port_file,
|
|
|
|
r
|
|
|
|
);
|
|
|
|
})
|
|
|
|
.catch(function () {
|
|
|
|
print('Failed to write the port file.');
|
|
|
|
});
|
|
|
|
}
|
2023-12-30 13:59:02 -05:00
|
|
|
|
2024-02-24 11:09:34 -05:00
|
|
|
if (tildefriends.https_port) {
|
|
|
|
async function start_tls() {
|
|
|
|
const kCertificatePath = 'data/httpd/certificate.pem';
|
|
|
|
const kPrivateKeyPath = 'data/httpd/privatekey.pem';
|
2024-04-28 12:25:12 -04:00
|
|
|
let privateKey;
|
|
|
|
let certificate;
|
|
|
|
try {
|
|
|
|
privateKey = utf8Decode(await File.readFile(kPrivateKeyPath));
|
|
|
|
certificate = utf8Decode(await File.readFile(kCertificatePath));
|
|
|
|
} catch (e) {
|
|
|
|
print(`TLS disabled (${e.message}).`);
|
|
|
|
return;
|
|
|
|
}
|
2024-02-24 11:09:34 -05:00
|
|
|
let context = new TlsContext();
|
|
|
|
context.setPrivateKey(privateKey);
|
|
|
|
context.setCertificate(certificate);
|
|
|
|
httpd.start(tildefriends.https_port, context);
|
|
|
|
}
|
|
|
|
start_tls();
|
2023-12-30 13:59:02 -05:00
|
|
|
}
|
2024-02-24 11:09:34 -05:00
|
|
|
})
|
|
|
|
.catch(function (error) {
|
|
|
|
print('Failed to load settings.');
|
|
|
|
printError({print: print}, error);
|
|
|
|
exit(1);
|
|
|
|
});
|
2022-03-17 21:24:29 -04:00
|
|
|
|
2024-10-16 19:50:31 -04:00
|
|
|
export {invoke, getProcessBlob};
|