ssb: Move identity info gathering to db.
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 26m52s
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 26m52s
This commit is contained in:
parent
bc70e41b7c
commit
0f573ce09e
117
src/ssb.db.c
117
src/ssb.db.c
@ -2331,3 +2331,120 @@ bool tf_ssb_db_has_invite(sqlite3* db, const char* id)
|
||||
}
|
||||
return has;
|
||||
}
|
||||
|
||||
static void _tf_ssb_db_get_identity_info_visit(const char* identity, void* user_data)
|
||||
{
|
||||
tf_ssb_identity_info_t* info = user_data;
|
||||
info->identity = tf_resize_vec(info->identity, (info->count + 1) * sizeof(char*));
|
||||
info->name = tf_resize_vec(info->name, (info->count + 1) * sizeof(char*));
|
||||
char buffer[k_id_base64_len];
|
||||
snprintf(buffer, sizeof(buffer), "@%s", identity);
|
||||
info->identity[info->count] = tf_strdup(buffer);
|
||||
info->name[info->count] = NULL;
|
||||
info->count++;
|
||||
}
|
||||
|
||||
tf_ssb_identity_info_t* tf_ssb_db_get_identity_info(tf_ssb_t* ssb, const char* user, const char* package_owner, const char* package_name)
|
||||
{
|
||||
tf_ssb_identity_info_t* info = tf_malloc(sizeof(tf_ssb_identity_info_t));
|
||||
*info = (tf_ssb_identity_info_t) { 0 };
|
||||
|
||||
char id[k_id_base64_len] = "";
|
||||
if (tf_ssb_db_user_has_permission(ssb, NULL, user, "administration"))
|
||||
{
|
||||
if (tf_ssb_whoami(ssb, id, sizeof(id)))
|
||||
{
|
||||
_tf_ssb_db_get_identity_info_visit(*id == '@' ? id + 1 : id, info);
|
||||
}
|
||||
}
|
||||
tf_ssb_db_identity_visit(ssb, user, _tf_ssb_db_get_identity_info_visit, info);
|
||||
|
||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||
sqlite3_stmt* statement = NULL;
|
||||
int 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 = ('@' || identities.public_key) "
|
||||
" WHERE "
|
||||
" (identities.user = ? OR identities.public_key = ?) 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 (result == SQLITE_OK)
|
||||
{
|
||||
if (sqlite3_bind_text(statement, 1, user, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, *id == '@' ? id + 1 : id, -1, NULL) == SQLITE_OK)
|
||||
{
|
||||
int r = SQLITE_OK;
|
||||
while ((r = sqlite3_step(statement)) == SQLITE_ROW)
|
||||
{
|
||||
const char* identity = (const char*)sqlite3_column_text(statement, 0);
|
||||
const char* name = (const char*)sqlite3_column_text(statement, 1);
|
||||
for (int i = 0; i < info->count; i++)
|
||||
{
|
||||
if (!info->name[i] && strcmp(info->identity[i], identity) == 0)
|
||||
{
|
||||
info->name[i] = tf_strdup(name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(statement);
|
||||
}
|
||||
else
|
||||
{
|
||||
tf_printf("prepare failed: %s.\n", sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
tf_ssb_db_identity_get_active(db, user, package_owner, package_name, info->active_identity, sizeof(info->active_identity));
|
||||
if (!*info->active_identity && info->count)
|
||||
{
|
||||
snprintf(info->active_identity, sizeof(info->active_identity), "%s", info->identity[0]);
|
||||
}
|
||||
tf_ssb_release_db_reader(ssb, db);
|
||||
|
||||
size_t size = sizeof(tf_ssb_identity_info_t) + sizeof(char*) * info->count * 2;
|
||||
for (int i = 0; i < info->count; i++)
|
||||
{
|
||||
size += strlen(info->identity[i]) + 1;
|
||||
size += info->name[i] ? strlen(info->name[i]) + 1 : 0;
|
||||
}
|
||||
tf_ssb_identity_info_t* copy = tf_malloc(size);
|
||||
*copy = *info;
|
||||
|
||||
copy->identity = (const char**)(copy + 1);
|
||||
copy->name = (const char**)(copy + 1) + copy->count;
|
||||
|
||||
char* p = (char*)((const char**)(copy + 1) + copy->count * 2);
|
||||
|
||||
for (int i = 0; i < info->count; i++)
|
||||
{
|
||||
size_t length = strlen(info->identity[i]);
|
||||
memcpy(p, info->identity[i], length + 1);
|
||||
copy->identity[i] = p;
|
||||
p += length + 1;
|
||||
tf_free((void*)info->identity[i]);
|
||||
|
||||
if (info->name[i])
|
||||
{
|
||||
length = strlen(info->name[i]);
|
||||
memcpy(p, info->name[i], length + 1);
|
||||
copy->name[i] = p;
|
||||
p += length + 1;
|
||||
tf_free((void*)info->name[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
copy->name[i] = NULL;
|
||||
}
|
||||
}
|
||||
tf_free(info->name);
|
||||
tf_free(info->identity);
|
||||
tf_free(info);
|
||||
return copy;
|
||||
}
|
||||
|
25
src/ssb.db.h
25
src/ssb.db.h
@ -564,4 +564,29 @@ int tf_ssb_sqlite_authorizer(void* user_data, int action_code, const char* arg0,
|
||||
*/
|
||||
bool tf_ssb_db_has_invite(sqlite3* db, const char* id);
|
||||
|
||||
/**
|
||||
** Identity information
|
||||
*/
|
||||
typedef struct _tf_ssb_identity_info_t
|
||||
{
|
||||
/** An array of identities. */
|
||||
const char** identity;
|
||||
/** A array of identities, one for each identity. */
|
||||
const char** name;
|
||||
/** The number of elements in both the identity and name arrays. */
|
||||
int count;
|
||||
/** The active identity. */
|
||||
char active_identity[k_id_base64_len];
|
||||
} tf_ssb_identity_info_t;
|
||||
|
||||
/**
|
||||
** Get available identities, names, and the active identity for a user.
|
||||
** @param ssb The SSB instance.
|
||||
** @param user The user name.
|
||||
** @param package_owner The owner of the package for which identity info is being fetched.
|
||||
** @param package_name The name of the package for which identity info is being fetched.
|
||||
** @return A struct of identities, names, and the active identity. Free with tf_free().
|
||||
*/
|
||||
tf_ssb_identity_info_t* tf_ssb_db_get_identity_info(tf_ssb_t* ssb, const char* user, const char* package_owner, const char* package_name);
|
||||
|
||||
/** @} */
|
||||
|
95
src/ssb.js.c
95
src/ssb.js.c
@ -613,87 +613,14 @@ typedef struct _identity_info_work_t
|
||||
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];
|
||||
tf_ssb_identity_info_t* info;
|
||||
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*));
|
||||
char buffer[k_id_base64_len];
|
||||
snprintf(buffer, sizeof(buffer), "@%s", identity);
|
||||
request->identities[request->count] = tf_strdup(buffer);
|
||||
request->names[request->count] = NULL;
|
||||
request->count++;
|
||||
}
|
||||
|
||||
static void _tf_ssb_getIdentityInfo_work(tf_ssb_t* ssb, void* user_data)
|
||||
{
|
||||
identity_info_work_t* request = user_data;
|
||||
char id[k_id_base64_len] = "";
|
||||
if (tf_ssb_db_user_has_permission(ssb, NULL, request->name, "administration"))
|
||||
{
|
||||
if (tf_ssb_whoami(ssb, id, sizeof(id)))
|
||||
{
|
||||
_tf_ssb_getIdentityInfo_visit(*id == '@' ? id + 1 : id, request);
|
||||
}
|
||||
}
|
||||
tf_ssb_db_identity_visit(ssb, request->name, _tf_ssb_getIdentityInfo_visit, request);
|
||||
|
||||
sqlite3* db = tf_ssb_acquire_db_reader(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 = ('@' || identities.public_key) "
|
||||
" WHERE "
|
||||
" (identities.user = ? OR identities.public_key = ?) 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 && sqlite3_bind_text(statement, 2, *id == '@' ? id + 1 : id, -1, NULL) == SQLITE_OK)
|
||||
{
|
||||
int r = SQLITE_OK;
|
||||
while ((r = sqlite3_step(statement)) == SQLITE_ROW)
|
||||
{
|
||||
const char* identity = (const char*)sqlite3_column_text(statement, 0);
|
||||
const char* name = (const char*)sqlite3_column_text(statement, 1);
|
||||
for (int i = 0; i < request->count; i++)
|
||||
{
|
||||
if (!request->names[i] && strcmp(request->identities[i], identity) == 0)
|
||||
{
|
||||
request->names[i] = tf_strdup(name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(statement);
|
||||
}
|
||||
else
|
||||
{
|
||||
tf_printf("prepare failed: %s.\n", sqlite3_errmsg(db));
|
||||
}
|
||||
|
||||
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(ssb, db);
|
||||
request->info = tf_ssb_db_get_identity_info(ssb, request->name, request->package_owner, request->package_name);
|
||||
}
|
||||
|
||||
static void _tf_ssb_getIdentityInfo_after_work(tf_ssb_t* ssb, int status, void* user_data)
|
||||
@ -703,20 +630,20 @@ static void _tf_ssb_getIdentityInfo_after_work(tf_ssb_t* ssb, int status, void*
|
||||
JSValue result = JS_NewObject(context);
|
||||
|
||||
JSValue identities = JS_NewArray(context);
|
||||
for (int i = 0; i < request->count; i++)
|
||||
for (int i = 0; i < request->info->count; i++)
|
||||
{
|
||||
JS_SetPropertyUint32(context, identities, i, JS_NewString(context, request->identities[i]));
|
||||
JS_SetPropertyUint32(context, identities, i, JS_NewString(context, request->info->identity[i]));
|
||||
}
|
||||
JS_SetPropertyStr(context, result, "identities", identities);
|
||||
|
||||
JSValue names = JS_NewObject(context);
|
||||
for (int i = 0; i < request->count; i++)
|
||||
for (int i = 0; i < request->info->count; i++)
|
||||
{
|
||||
JS_SetPropertyStr(context, names, request->identities[i], JS_NewString(context, request->names[i] ? request->names[i] : request->identities[i]));
|
||||
JS_SetPropertyStr(context, names, request->info->identity[i], JS_NewString(context, request->info->name[i] ? request->info->name[i] : request->info->identity[i]));
|
||||
}
|
||||
JS_SetPropertyStr(context, result, "names", names);
|
||||
|
||||
JS_SetPropertyStr(context, result, "identity", JS_NewString(context, request->active_identity));
|
||||
JS_SetPropertyStr(context, result, "identity", JS_NewString(context, request->info->active_identity));
|
||||
|
||||
JSValue error = JS_Call(context, request->promise[0], JS_UNDEFINED, 1, &result);
|
||||
tf_util_report_error(context, error);
|
||||
@ -725,16 +652,10 @@ static void _tf_ssb_getIdentityInfo_after_work(tf_ssb_t* ssb, int status, void*
|
||||
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->info);
|
||||
tf_free(request);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user