Compare commits

..

No commits in common. "0e7d2a8b0e7954c773b31dbf879727a73a9b4dd1" and "700dd7b45af9b368e077cf4028e003c9bc0fa324" have entirely different histories.

6 changed files with 29 additions and 169 deletions

View File

@ -1,5 +1,5 @@
{ {
"type": "tildefriends-app", "type": "tildefriends-app",
"emoji": "🪪", "emoji": "🪪",
"previous": "&5kw/2PgcySwOYCmAkjHTR2xTkIx3i7UjQmtQ8MfgWw8=.sha256" "previous": "&zxsmzdLKsiG/WZt/Gw7JOxepgypoktNNbIyWiyFiJVc=.sha256"
} }

View File

@ -1,7 +1,5 @@
import * as tfrpc from '/tfrpc.js'; import * as tfrpc from '/tfrpc.js';
const is_admin = core.user?.credentials?.permissions?.administration;
tfrpc.register(async function get_private_key(id) { tfrpc.register(async function get_private_key(id) {
return bip39Words(await ssb.getPrivateKey(id)); return bip39Words(await ssb.getPrivateKey(id));
}); });
@ -17,9 +15,6 @@ tfrpc.register(async function delete_id(id) {
tfrpc.register(async function reload() { tfrpc.register(async function reload() {
await main(); await main();
}); });
tfrpc.register(async function make_server(id) {
return await ssb.swapWithServerIdentity(id);
});
async function main() { async function main() {
let ids = await ssb.getIdentities(); let ids = await ssb.getIdentities();
@ -104,16 +99,6 @@ async function main() {
alert('Error deleting ID: ' + e); alert('Error deleting ID: ' + e);
} }
} }
handler.make_server = async function make_server(event) {
let id = event.srcElement.dataset.id;
try {
if (confirm('Are you sure you want to make "' + id + '" the server identity?\\n\\nFor it to take effect, you will need to both sign in again and restart Tilde Friends.')) {
await tfrpc.rpc.make_server(id);
}
} catch (e) {
alert('Error making server ID: ' + e);
}
}
</script> </script>
<header class="w3-theme w3-padding"><h1>SSB Identity Management</h1></header> <header class="w3-theme w3-padding"><h1>SSB Identity Management</h1></header>
<div class="w3-card-4 w3-margin"> <div class="w3-card-4 w3-margin">
@ -132,14 +117,13 @@ async function main() {
<div class="w3-card-4 w3-margin"> <div class="w3-card-4 w3-margin">
<header class="w3-container w3-theme-l2"><h2>Identities</h2></header> <header class="w3-container w3-theme-l2"><h2>Identities</h2></header>
<ul class="w3-ul">` + <ul class="w3-ul">` +
(ids ?? []) ids
.map( .map(
( (
id id
) => `<li style="overflow: hidden; text-wrap: nowrap; text-overflow: ellipsis"> ) => `<li style="overflow: hidden; text-wrap: nowrap; text-overflow: ellipsis">
<button onclick="handler.export_id(event)" data-id="${id}" class="w3-button w3-theme">Export Identity</button> <button onclick="handler.export_id(event)" data-id="${id}" class="w3-button w3-theme">Export Identity</button>
<button onclick="handler.delete_id(event)" data-id="${id}" class="w3-button w3-theme">Delete Identity</button> <button onclick="handler.delete_id(event)" data-id="${id}" class="w3-button w3-theme">Delete Identity</button>
${is_admin && id != server_id ? `<button onclick="handler.make_server(event)" data-id="${id}" class="w3-button w3-theme">Make Server Identity</button>` : ''}
${id}${id == server_id ? ' <div class="w3-tag w3-theme-l4 w3-round">🖥 local server</div>' : ''} ${id}${id == server_id ? ' <div class="w3-tag w3-theme-l4 w3-round">🖥 local server</div>' : ''}
</li>` </li>`
) )

View File

@ -72,21 +72,16 @@
<a <a
class="w3-button w3-round-large w3-padding w3-blue-gray w3-margin-top" class="w3-button w3-round-large w3-padding w3-blue-gray w3-margin-top"
href="https://f-droid.org/en/packages/com.unprompted.tildefriends.fdroid/" href="https://f-droid.org/en/packages/com.unprompted.tildefriends.fdroid/"
><img src="f-droid.svg" style="height: 2em; margin: 0" /> Get it ><img src="f-droid.svg" style="height: 2em; margin: 0"
on F-Droid</a /> Get it on F-Droid</a>
> <a class="w3-button w3-round-large w3-padding w3-blue-gray w3-margin-top"
<a href="https://dev.tildefriends.net/releases/tildefriends-x86_64.AppImage">
class="w3-button w3-round-large w3-padding w3-blue-gray w3-margin-top" <img src="appimage.svg" style="height: 2em; margin: 0">
href="https://dev.tildefriends.net/releases/tildefriends-x86_64.AppImage"
>
<img src="appimage.svg" style="height: 2em; margin: 0" />
Get Linux 64-bit AppImage Get Linux 64-bit AppImage
</a> </a>
<a <a class="w3-button w3-round-large w3-padding w3-blue-gray w3-margin-top"
class="w3-button w3-round-large w3-padding w3-blue-gray w3-margin-top" href="https://play.google.com/store/apps/details?id=com.unprompted.tildefriends">
href="https://play.google.com/store/apps/details?id=com.unprompted.tildefriends" <img src="googleplay.svg" style="height: 2em; margin: 0">
>
<img src="googleplay.svg" style="height: 2em; margin: 0" />
Get it on Google Play (Open Testing) Get it on Google Play (Open Testing)
</a> </a>
</p> </p>
@ -115,26 +110,22 @@
>https://www.tildefriends.net/</a >https://www.tildefriends.net/</a
>. >.
</li> </li>
<li>Create an account to identify yourself with that instance.</li> <li>
Create an account to identify yourself with that instance.
</li>
<li> <li>
Describe yourself in your profile in the <b>ssb</b> app. Give Describe yourself in your profile in the <b>ssb</b> app. Give
yourself a name and an avatar if you like. yourself a name and an avatar if you like.
</li> </li>
<li> <li>
Connect to others. Connect to others.
<ul> <ul>
<li>Automatically discover peers on the same network.</li> <li>Automatically discover peers on the same network.</li>
<li> <li>Manually connect to rooms and pubs, including <a href="https://www.tildefriends.net/~cory/room/"
Manually connect to rooms and pubs, including
<a href="https://www.tildefriends.net/~cory/room/"
>tildefriends.net itself</a >tildefriends.net itself</a
>. >.</li>
</li> <li>Enable <b>Peer Exchange</b> in the <b>admin</b> to discover internet peers.</li>
<li> </ul>
Enable <b>Peer Exchange</b> in the <b>admin</b> to discover
internet peers.
</li>
</ul>
</li> </li>
<li>Follow people to grow your network.</li> <li>Follow people to grow your network.</li>
<li> <li>
@ -225,11 +216,10 @@
<div class="w3-container w3-padding-64 w3-light-grey w3-center"> <div class="w3-container w3-padding-64 w3-light-grey w3-center">
<h1 class="w3-jumbo"><b>Boring Technology</b></h1> <h1 class="w3-jumbo"><b>Boring Technology</b></h1>
<p> <p>
Tilde Friends is built using boring, trusted tech. Unless a better Tilde Friends is built using boring, trusted tech. Unless a better reason
reason presents itself, it strives to use only simple and widely adopted presents itself, it strives to use only simple and
dependencies in order to keep it easy to build for all sorts of widely adopted dependencies in order to keep it easy to build for
platforms and maintainable for a very long time. all sorts of platforms and maintainable for a very long time.</p>
</p>
<p> <p>
Though of course for building Tilde Friends apps, you are free to use Though of course for building Tilde Friends apps, you are free to use
whatever fits. whatever fits.

View File

@ -692,18 +692,6 @@ async function getProcessBlob(blobId, key, options) {
); );
} }
}; };
imports.ssb.swapWithServerIdentity = function (id) {
if (
process.credentials &&
process.credentials.session &&
process.credentials.session.name
) {
return ssb.swapWithServerIdentity(
process.credentials.session.name,
id
);
}
};
imports.ssb.addEventListener = undefined; imports.ssb.addEventListener = undefined;
imports.ssb.removeEventListener = undefined; imports.ssb.removeEventListener = undefined;
imports.ssb.getIdentityInfo = undefined; imports.ssb.getIdentityInfo = undefined;

View File

@ -360,109 +360,6 @@ static JSValue _tf_ssb_set_server_following_me(JSContext* context, JSValueConst
return result; return result;
} }
typedef struct _swap_with_server_identity_t
{
char server_id[k_id_base64_len];
char id[k_id_base64_len];
JSValue promise[2];
char* error;
char user[];
} swap_with_server_identity_t;
static void _tf_ssb_swap_with_server_identity_work(tf_ssb_t* ssb, void* user_data)
{
swap_with_server_identity_t* work = user_data;
if (tf_ssb_db_user_has_permission(ssb, work->user, "administration"))
{
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
char* error = NULL;
if (sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, &error) == SQLITE_OK)
{
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db, "UPDATE identities SET user = ? WHERE user = ? AND '@' || public_key = ?", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, work->user, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, ":admin", -1, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, work->server_id, -1, NULL) == SQLITE_OK && sqlite3_step(statement) == SQLITE_DONE && sqlite3_changes(db) == 1 &&
sqlite3_reset(statement) == SQLITE_OK && sqlite3_bind_text(statement, 1, ":admin", -1, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 2, work->user, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 3, work->id, -1, NULL) == SQLITE_OK &&
sqlite3_step(statement) == SQLITE_DONE && sqlite3_changes(db) == 1)
{
error = NULL;
if (sqlite3_exec(db, "COMMIT TRANSACTION", NULL, NULL, &error) != SQLITE_OK)
{
work->error = error ? tf_strdup(error) : tf_strdup(sqlite3_errmsg(db));
}
}
else
{
work->error = tf_strdup(sqlite3_errmsg(db) ? sqlite3_errmsg(db) : "swap failed");
}
sqlite3_finalize(statement);
}
else
{
work->error = tf_strdup(sqlite3_errmsg(db));
}
}
else
{
work->error = error ? tf_strdup(error) : tf_strdup(sqlite3_errmsg(db));
}
tf_ssb_release_db_writer(ssb, db);
}
else
{
work->error = tf_strdup("not administrator");
}
}
static void _tf_ssb_swap_with_server_identity_after_work(tf_ssb_t* ssb, int status, void* user_data)
{
swap_with_server_identity_t* work = user_data;
JSContext* context = tf_ssb_get_context(ssb);
JSValue error = JS_UNDEFINED;
if (work->error)
{
JSValue arg = JS_ThrowInternalError(context, "%s", work->error);
JSValue exception = JS_GetException(context);
error = JS_Call(context, work->promise[1], JS_UNDEFINED, 1, &exception);
tf_free(work->error);
JS_FreeValue(context, exception);
JS_FreeValue(context, arg);
}
else
{
error = JS_Call(context, work->promise[0], JS_UNDEFINED, 0, NULL);
}
tf_util_report_error(context, error);
JS_FreeValue(context, error);
JS_FreeValue(context, work->promise[0]);
JS_FreeValue(context, work->promise[1]);
tf_free(work);
}
static JSValue _tf_ssb_swap_with_server_identity(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{
tf_ssb_t* ssb = JS_GetOpaque(this_val, _tf_ssb_classId);
JSValue result = JS_UNDEFINED;
if (ssb)
{
size_t user_length = 0;
const char* user = JS_ToCStringLen(context, &user_length, argv[0]);
const char* id = JS_ToCString(context, argv[1]);
swap_with_server_identity_t* work = tf_malloc(sizeof(swap_with_server_identity_t) + user_length + 1);
*work = (swap_with_server_identity_t) { 0 };
tf_ssb_whoami(ssb, work->server_id, sizeof(work->server_id));
snprintf(work->id, sizeof(work->id), "%s", id);
memcpy(work->user, user, user_length + 1);
result = JS_NewPromiseCapability(context, work->promise);
tf_ssb_run_work(ssb, _tf_ssb_swap_with_server_identity_work, _tf_ssb_swap_with_server_identity_after_work, work);
JS_FreeCString(context, user);
JS_FreeCString(context, id);
}
return result;
}
typedef struct _identities_visit_t typedef struct _identities_visit_t
{ {
JSContext* context; JSContext* context;
@ -2415,7 +2312,6 @@ void tf_ssb_register(JSContext* context, tf_ssb_t* ssb)
JS_SetPropertyStr(context, object, "addIdentity", JS_NewCFunction(context, _tf_ssb_addIdentity, "addIdentity", 2)); JS_SetPropertyStr(context, object, "addIdentity", JS_NewCFunction(context, _tf_ssb_addIdentity, "addIdentity", 2));
JS_SetPropertyStr(context, object, "deleteIdentity", JS_NewCFunction(context, _tf_ssb_deleteIdentity, "deleteIdentity", 2)); JS_SetPropertyStr(context, object, "deleteIdentity", JS_NewCFunction(context, _tf_ssb_deleteIdentity, "deleteIdentity", 2));
JS_SetPropertyStr(context, object, "setServerFollowingMe", JS_NewCFunction(context, _tf_ssb_set_server_following_me, "setServerFollowingMe", 3)); JS_SetPropertyStr(context, object, "setServerFollowingMe", JS_NewCFunction(context, _tf_ssb_set_server_following_me, "setServerFollowingMe", 3));
JS_SetPropertyStr(context, object, "swapWithServerIdentity", JS_NewCFunction(context, _tf_ssb_swap_with_server_identity, "swapWithServerIdentity", 2));
JS_SetPropertyStr(context, object, "getIdentities", JS_NewCFunction(context, _tf_ssb_getIdentities, "getIdentities", 1)); JS_SetPropertyStr(context, object, "getIdentities", JS_NewCFunction(context, _tf_ssb_getIdentities, "getIdentities", 1));
JS_SetPropertyStr(context, object, "getPrivateKey", JS_NewCFunction(context, _tf_ssb_getPrivateKey, "getPrivateKey", 2)); JS_SetPropertyStr(context, object, "getPrivateKey", JS_NewCFunction(context, _tf_ssb_getPrivateKey, "getPrivateKey", 2));
JS_SetPropertyStr(context, object, "privateMessageEncrypt", JS_NewCFunction(context, _tf_ssb_private_message_encrypt, "privateMessageEncrypt", 4)); JS_SetPropertyStr(context, object, "privateMessageEncrypt", JS_NewCFunction(context, _tf_ssb_private_message_encrypt, "privateMessageEncrypt", 4));

View File

@ -1295,15 +1295,17 @@ static void _tf_ssb_rpc_connections_changed_callback(tf_ssb_t* ssb, tf_ssb_chang
} }
} }
static void _tf_ssb_rpc_broadcasts_changed_visit( static void _tf_ssb_rpc_broadcasts_changed_visit(const char* host, const struct sockaddr_in* addr, tf_ssb_broadcast_origin_t origin, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data)
const char* host, const struct sockaddr_in* addr, tf_ssb_broadcast_origin_t origin, tf_ssb_connection_t* tunnel, const uint8_t* pub, void* user_data)
{ {
tf_ssb_t* ssb = user_data; tf_ssb_t* ssb = user_data;
if (tunnel && (tf_ssb_connection_get_flags(tunnel) & k_tf_ssb_connect_flag_one_shot) != 0 && !tf_ssb_connection_get_tunnel(tunnel)) if (tunnel &&
(tf_ssb_connection_get_flags(tunnel) & k_tf_ssb_connect_flag_one_shot) != 0 &&
!tf_ssb_connection_get_tunnel(tunnel))
{ {
char target_id[k_id_base64_len] = { 0 }; char target_id[k_id_base64_len] = { 0 };
char portal_id[k_id_base64_len] = { 0 }; char portal_id[k_id_base64_len] = { 0 };
if (tf_ssb_id_bin_to_str(target_id, sizeof(target_id), pub) && tf_ssb_connection_get_id(tunnel, portal_id, sizeof(portal_id))) if (tf_ssb_id_bin_to_str(target_id, sizeof(target_id), pub) &&
tf_ssb_connection_get_id(tunnel, portal_id, sizeof(portal_id)))
{ {
tf_ssb_tunnel_create(ssb, portal_id, target_id, k_tf_ssb_connect_flag_one_shot); tf_ssb_tunnel_create(ssb, portal_id, target_id, k_tf_ssb_connect_flag_one_shot);
} }