forked from cory/tildefriends
		
	getIdentityInfo => C.
This commit is contained in:
		@@ -149,7 +149,7 @@ function socket(request, response, client) {
 | 
			
		||||
								parentApp: parentApp,
 | 
			
		||||
								id: blobId,
 | 
			
		||||
							},
 | 
			
		||||
							await core.getIdentityInfo(
 | 
			
		||||
							await ssb.getIdentityInfo(
 | 
			
		||||
								credentials?.session?.name,
 | 
			
		||||
								packageOwner,
 | 
			
		||||
								packageName
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								core/core.js
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								core/core.js
									
									
									
									
									
								
							@@ -545,7 +545,7 @@ async function getProcessBlob(blobId, key, options) {
 | 
			
		||||
						{
 | 
			
		||||
							action: 'identities',
 | 
			
		||||
						},
 | 
			
		||||
						await getIdentityInfo(
 | 
			
		||||
						await ssb.getIdentityInfo(
 | 
			
		||||
							process?.credentials?.session?.name,
 | 
			
		||||
							options?.packageOwner,
 | 
			
		||||
							options?.packageName
 | 
			
		||||
@@ -785,6 +785,7 @@ async function getProcessBlob(blobId, key, options) {
 | 
			
		||||
					);
 | 
			
		||||
				}
 | 
			
		||||
			};
 | 
			
		||||
			imports.ssb.getIdentityInfo = undefined;
 | 
			
		||||
			imports.fetch = function (url, options) {
 | 
			
		||||
				return http.fetch(url, options, gGlobalSettings.fetch_hosts);
 | 
			
		||||
			};
 | 
			
		||||
@@ -1553,43 +1554,10 @@ function storePermission(user, packageOwner, packageName, permission, allow) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function getIdentityInfo(user, packageOwner, packageName) {
 | 
			
		||||
	let identities = await ssb.getIdentities(user);
 | 
			
		||||
	let names = new Object();
 | 
			
		||||
	for (let identity of identities) {
 | 
			
		||||
		names[identity] = identity;
 | 
			
		||||
	}
 | 
			
		||||
	await ssb.sqlAsync(
 | 
			
		||||
		`
 | 
			
		||||
		SELECT author, name FROM (
 | 
			
		||||
			SELECT
 | 
			
		||||
				messages.author,
 | 
			
		||||
				RANK() OVER (PARTITION BY messages.author ORDER BY messages.sequence DESC) AS author_rank,
 | 
			
		||||
				messages.content ->> 'name' AS name
 | 
			
		||||
			FROM messages
 | 
			
		||||
			JOIN json_each(?) AS ids
 | 
			
		||||
			ON messages.author = ids.value
 | 
			
		||||
			WHERE json_extract(messages.content, '$.type') = 'about' AND content ->> 'about' = messages.author AND name IS NOT NULL)
 | 
			
		||||
		WHERE author_rank = 1
 | 
			
		||||
		`,
 | 
			
		||||
		[JSON.stringify(identities)],
 | 
			
		||||
		function (row) {
 | 
			
		||||
			names[row.author] = row.name;
 | 
			
		||||
		}
 | 
			
		||||
	);
 | 
			
		||||
 | 
			
		||||
	return {
 | 
			
		||||
		identities: identities,
 | 
			
		||||
		identity: await ssb.getActiveIdentity(user, packageOwner, packageName),
 | 
			
		||||
		names: names,
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export {
 | 
			
		||||
	gGlobalSettings as globalSettings,
 | 
			
		||||
	setGlobalSettings,
 | 
			
		||||
	enableStats,
 | 
			
		||||
	invoke,
 | 
			
		||||
	getSessionProcessBlob,
 | 
			
		||||
	getIdentityInfo,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								src/ssb.db.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								src/ssb.db.c
									
									
									
									
									
								
							@@ -1735,3 +1735,22 @@ bool tf_ssb_db_set_property(tf_ssb_t* ssb, const char* id, const char* key, cons
 | 
			
		||||
	tf_ssb_release_db_writer(ssb, db);
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool tf_ssb_db_identity_get_active(sqlite3* db, const char* user, const char* package_owner, const char* package_name, char* out_identity, size_t out_identity_size)
 | 
			
		||||
{
 | 
			
		||||
	sqlite3_stmt* statement = NULL;
 | 
			
		||||
	bool found = false;
 | 
			
		||||
	if (sqlite3_prepare(db, "SELECT value FROM properties WHERE id = ? AND key = 'id:' || ? || ':' || ?", -1, &statement, NULL) == SQLITE_OK)
 | 
			
		||||
	{
 | 
			
		||||
		if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK &&
 | 
			
		||||
			sqlite3_bind_text(statement, 2, package_owner, -1, NULL) == SQLITE_OK &&
 | 
			
		||||
			sqlite3_bind_text(statement, 3, package_name, -1, NULL) == SQLITE_OK &&
 | 
			
		||||
			sqlite3_step(statement) == SQLITE_ROW)
 | 
			
		||||
		{
 | 
			
		||||
			snprintf(out_identity, out_identity_size, "%s", (const char*)sqlite3_column_text(statement, 0));
 | 
			
		||||
			found = true;
 | 
			
		||||
		}
 | 
			
		||||
		sqlite3_finalize(statement);
 | 
			
		||||
	}
 | 
			
		||||
	return found;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								src/ssb.db.h
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								src/ssb.db.h
									
									
									
									
									
								
							@@ -195,6 +195,18 @@ bool tf_ssb_db_identity_delete(tf_ssb_t* ssb, const char* user, const char* publ
 | 
			
		||||
*/
 | 
			
		||||
bool tf_ssb_db_identity_add(tf_ssb_t* ssb, const char* user, const char* public_key, const char* private_key);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
** Get the active identity for a user for a given package.
 | 
			
		||||
** @param db An sqlite3 database.
 | 
			
		||||
** @param user The username.
 | 
			
		||||
** @param package_owner The username of the package owner.
 | 
			
		||||
** @param package_name The name of the package.
 | 
			
		||||
** @param[out] out_identity Populated with the identity.
 | 
			
		||||
** @param out_identity_size The size of the out_identity buffer.
 | 
			
		||||
** @return true If the identity was retrieved.
 | 
			
		||||
*/
 | 
			
		||||
bool tf_ssb_db_identity_get_active(sqlite3* db, const char* user, const char* package_owner, const char* package_name, char* out_identity, size_t out_identity_size);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
** Call a function for each identity owned by a user.
 | 
			
		||||
** @param ssb The SSB instance.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										158
									
								
								src/ssb.js.c
									
									
									
									
									
								
							
							
						
						
									
										158
									
								
								src/ssb.js.c
									
									
									
									
									
								
							@@ -330,19 +330,7 @@ static void _tf_ssb_getActiveIdentity_work(uv_work_t* work)
 | 
			
		||||
	tf_trace_begin(trace, "_tf_ssb_getActiveIdentity_work");
 | 
			
		||||
 | 
			
		||||
	sqlite3* db = tf_ssb_acquire_db_reader(request->ssb);
 | 
			
		||||
	sqlite3_stmt* statement = NULL;
 | 
			
		||||
	request->result = sqlite3_prepare(db, "SELECT value FROM properties WHERE id = ? AND key = 'id:' || ? || ':' || ?", -1, &statement, NULL);
 | 
			
		||||
	if (request->result == SQLITE_OK)
 | 
			
		||||
	{
 | 
			
		||||
		if (sqlite3_bind_text(statement, 1, request->name, -1, NULL) == SQLITE_OK &&
 | 
			
		||||
			sqlite3_bind_text(statement, 2, request->package_owner, -1, NULL) == SQLITE_OK &&
 | 
			
		||||
			sqlite3_bind_text(statement, 3, request->package_name, -1, NULL) == SQLITE_OK &&
 | 
			
		||||
			sqlite3_step(statement) == SQLITE_ROW)
 | 
			
		||||
		{
 | 
			
		||||
			snprintf(request->identity, sizeof(request->identity), "%s", (const char*)sqlite3_column_text(statement, 0));
 | 
			
		||||
		}
 | 
			
		||||
		sqlite3_finalize(statement);
 | 
			
		||||
	}
 | 
			
		||||
	tf_ssb_db_identity_get_active(db, request->name, request->package_owner, request->package_name, request->identity, sizeof(request->identity));
 | 
			
		||||
	tf_ssb_release_db_reader(request->ssb, db);
 | 
			
		||||
 | 
			
		||||
	if (!*request->identity)
 | 
			
		||||
@@ -408,6 +396,149 @@ static JSValue _tf_ssb_getActiveIdentity(JSContext* context, JSValueConst this_v
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct _identity_info_work_t
 | 
			
		||||
{
 | 
			
		||||
	uv_work_t request;
 | 
			
		||||
	tf_ssb_t* ssb;
 | 
			
		||||
	JSContext* context;
 | 
			
		||||
	const char* name;
 | 
			
		||||
	const char* package_owner;
 | 
			
		||||
	const char* package_name;
 | 
			
		||||
	int count;
 | 
			
		||||
	char** identities;
 | 
			
		||||
	char** names;
 | 
			
		||||
	int result;
 | 
			
		||||
	char active_identity[k_id_base64_len];
 | 
			
		||||
	JSValue promise[2];
 | 
			
		||||
} identity_info_work_t;
 | 
			
		||||
 | 
			
		||||
static void _tf_ssb_getIdentityInfo_visit(const char* identity, void* data)
 | 
			
		||||
{
 | 
			
		||||
	identity_info_work_t* request = data;
 | 
			
		||||
	request->identities = tf_resize_vec(request->identities, (request->count + 1) * sizeof(char*));
 | 
			
		||||
	request->names = tf_resize_vec(request->names, (request->count + 1) * sizeof(char*));
 | 
			
		||||
	request->identities[request->count] = tf_strdup(identity);
 | 
			
		||||
	request->names[request->count] = NULL;
 | 
			
		||||
	request->count++;;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _tf_ssb_getIdentityInfo_work(uv_work_t* work)
 | 
			
		||||
{
 | 
			
		||||
	identity_info_work_t* request = work->data;
 | 
			
		||||
	tf_ssb_db_identity_visit(request->ssb, request->name, _tf_ssb_getIdentityInfo_visit, request);
 | 
			
		||||
 | 
			
		||||
	sqlite3* db = tf_ssb_acquire_db_reader(request->ssb);
 | 
			
		||||
	sqlite3_stmt* statement = NULL;
 | 
			
		||||
	request->result = sqlite3_prepare(db,
 | 
			
		||||
		"SELECT author, name FROM ( "
 | 
			
		||||
		"	SELECT "
 | 
			
		||||
		"		messages.author, "
 | 
			
		||||
		"		RANK() OVER (PARTITION BY messages.author ORDER BY messages.sequence DESC) AS author_rank, "
 | 
			
		||||
		"		messages.content ->> 'name' AS name "
 | 
			
		||||
		"	FROM messages "
 | 
			
		||||
		"	JOIN identities ON  messages.author = ids.value "
 | 
			
		||||
		"	WHERE WHERE identities.user = ? AND json_extract(messages.content, '$.type') = 'about' AND content ->> 'about' = messages.author AND name IS NOT NULL) "
 | 
			
		||||
		"WHERE author_rank = 1 ", -1, &statement, NULL);
 | 
			
		||||
	if (request->result == SQLITE_OK)
 | 
			
		||||
	{
 | 
			
		||||
		if (sqlite3_bind_text(statement, 1, request->name, -1, NULL) == SQLITE_OK)
 | 
			
		||||
		{
 | 
			
		||||
			int r = SQLITE_OK;
 | 
			
		||||
			while ((r = sqlite3_step(statement)) == SQLITE_OK)
 | 
			
		||||
			{
 | 
			
		||||
				for (int i = 0; i < request->count; i++)
 | 
			
		||||
				{
 | 
			
		||||
					const char* identity = (const char*)sqlite3_column_text(statement, 0);
 | 
			
		||||
					const char* name = (const char*)sqlite3_column_text(statement, 1);
 | 
			
		||||
					if (strcmp(request->identities[i], identity) == 0 && !request->names[i])
 | 
			
		||||
					{
 | 
			
		||||
						request->names[i] = tf_strdup(name);
 | 
			
		||||
					}
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		sqlite3_finalize(statement);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tf_ssb_db_identity_get_active(db, request->name, request->package_owner, request->package_name, request->active_identity, sizeof(request->active_identity));
 | 
			
		||||
	if (!*request->active_identity && request->count)
 | 
			
		||||
	{
 | 
			
		||||
		snprintf(request->active_identity, sizeof(request->active_identity), "%s", request->identities[0]);
 | 
			
		||||
	}
 | 
			
		||||
	tf_ssb_release_db_reader(request->ssb, db);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void _tf_ssb_getIdentityInfo_after_work(uv_work_t* work, int status)
 | 
			
		||||
{
 | 
			
		||||
	identity_info_work_t* request = work->data;
 | 
			
		||||
	JSContext* context = request->context;
 | 
			
		||||
	JSValue result = JS_NewObject(context);
 | 
			
		||||
 | 
			
		||||
	JSValue identities = JS_NewArray(context);
 | 
			
		||||
	for (int i = 0; i < request->count; i++)
 | 
			
		||||
	{
 | 
			
		||||
		JS_SetPropertyUint32(context, identities, i, JS_NewString(context, request->identities[i]));
 | 
			
		||||
	}
 | 
			
		||||
	JS_SetPropertyStr(context, result, "identities", identities);
 | 
			
		||||
 | 
			
		||||
	JSValue names = JS_NewObject(context);
 | 
			
		||||
	for (int i = 0; i < request->count; i++)
 | 
			
		||||
	{
 | 
			
		||||
		JS_SetPropertyStr(context, names, request->identities[i], JS_NewString(context, request->names[i] ? request->names[i] : request->identities[i]));
 | 
			
		||||
	}
 | 
			
		||||
	JS_SetPropertyStr(context, result, "names", names);
 | 
			
		||||
 | 
			
		||||
	JS_SetPropertyStr(context, result, "identity", JS_NewString(context, request->active_identity));
 | 
			
		||||
 | 
			
		||||
	JSValue error = JS_Call(context, request->promise[0], JS_UNDEFINED, 1, &result);
 | 
			
		||||
	tf_util_report_error(context, error);
 | 
			
		||||
	JS_FreeValue(context, error);
 | 
			
		||||
	JS_FreeValue(context, result);
 | 
			
		||||
	JS_FreeValue(context, request->promise[0]);
 | 
			
		||||
	JS_FreeValue(context, request->promise[1]);
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i < request->count; i++)
 | 
			
		||||
	{
 | 
			
		||||
		tf_free(request->identities[i]);
 | 
			
		||||
		tf_free(request->names[i]);
 | 
			
		||||
	}
 | 
			
		||||
	tf_free(request->identities);
 | 
			
		||||
	tf_free(request->names);
 | 
			
		||||
	tf_free((void*)request->name);
 | 
			
		||||
	tf_free((void*)request->package_owner);
 | 
			
		||||
	tf_free((void*)request->package_name);
 | 
			
		||||
	tf_free(request);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static JSValue _tf_ssb_getIdentityInfo(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
 | 
			
		||||
{
 | 
			
		||||
	const char* name = JS_ToCString(context, argv[0]);
 | 
			
		||||
	const char* package_owner = JS_ToCString(context, argv[1]);
 | 
			
		||||
	const char* package_name = JS_ToCString(context, argv[2]);
 | 
			
		||||
	identity_info_work_t* work = tf_malloc(sizeof(identity_info_work_t));
 | 
			
		||||
	*work = (identity_info_work_t)
 | 
			
		||||
	{
 | 
			
		||||
		.request = { .data = work },
 | 
			
		||||
		.ssb = JS_GetOpaque(this_val, _tf_ssb_classId),
 | 
			
		||||
		.context = context,
 | 
			
		||||
		.name = tf_strdup(name),
 | 
			
		||||
		.package_owner = tf_strdup(package_owner),
 | 
			
		||||
		.package_name = tf_strdup(package_name),
 | 
			
		||||
	};
 | 
			
		||||
	JSValue result = JS_NewPromiseCapability(context, work->promise);
 | 
			
		||||
	JS_FreeCString(context, name);
 | 
			
		||||
	JS_FreeCString(context, package_owner);
 | 
			
		||||
	JS_FreeCString(context, package_name);
 | 
			
		||||
 | 
			
		||||
	int r = uv_queue_work(tf_ssb_get_loop(work->ssb), &work->request, _tf_ssb_getIdentityInfo_work, _tf_ssb_getIdentityInfo_after_work);
 | 
			
		||||
	if (r)
 | 
			
		||||
	{
 | 
			
		||||
		_tf_ssb_getIdentityInfo_after_work(&work->request, r);
 | 
			
		||||
	}
 | 
			
		||||
	return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
typedef struct _append_message_t
 | 
			
		||||
{
 | 
			
		||||
	JSContext* context;
 | 
			
		||||
@@ -1812,6 +1943,7 @@ void tf_ssb_register(JSContext* context, tf_ssb_t* ssb)
 | 
			
		||||
	JS_SetPropertyStr(context, object, "getServerIdentity", JS_NewCFunction(context, _tf_ssb_getServerIdentity, "getServerIdentity", 0));
 | 
			
		||||
	JS_SetPropertyStr(context, object, "getAllIdentities", JS_NewCFunction(context, _tf_ssb_getAllIdentities, "getAllIdentities", 0));
 | 
			
		||||
	JS_SetPropertyStr(context, object, "getActiveIdentity", JS_NewCFunction(context, _tf_ssb_getActiveIdentity, "getActiveIdentity", 3));
 | 
			
		||||
	JS_SetPropertyStr(context, object, "getIdentityInfo", JS_NewCFunction(context, _tf_ssb_getIdentityInfo, "getIdentityInfo", 3));
 | 
			
		||||
	JS_SetPropertyStr(context, object, "getMessage", JS_NewCFunction(context, _tf_ssb_getMessage, "getMessage", 2));
 | 
			
		||||
	JS_SetPropertyStr(context, object, "blobGet", JS_NewCFunction(context, _tf_ssb_blobGet, "blobGet", 1));
 | 
			
		||||
	JS_SetPropertyStr(context, object, "messageContentGet", JS_NewCFunction(context, _tf_ssb_messageContentGet, "messageContentGet", 1));
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user