Make http.auth_query async and get its DB work off the main thread.

This commit is contained in:
Cory McWilliams 2024-06-10 20:22:28 -04:00
parent c5140ee8e8
commit 58bb86ebe1
5 changed files with 67 additions and 40 deletions

View File

@ -83,10 +83,10 @@ App.prototype.send = function (message) {
* @param {*} response * @param {*} response
* @param {*} client * @param {*} client
*/ */
function socket(request, response, client) { async function socket(request, response, client) {
let process; let process;
let options = {}; let options = {};
let credentials = httpd.auth_query(request.headers); let credentials = await httpd.auth_query(request.headers);
response.onClose = async function () { response.onClose = async function () {
if (process && process.task) { if (process && process.task) {

View File

@ -908,7 +908,7 @@ async function useAppHandler(
}, },
respond: do_resolve, respond: do_resolve,
}, },
credentials: httpd.auth_query(headers), credentials: await httpd.auth_query(headers),
packageOwner: packageOwner, packageOwner: packageOwner,
packageName: packageName, packageName: packageName,
} }
@ -1039,7 +1039,7 @@ async function blobHandler(request, response, blobId, uri) {
if ((match = /^\/\~(\w+)\/(\w+)$/.exec(blobId))) { if ((match = /^\/\~(\w+)\/(\w+)$/.exec(blobId))) {
let user = match[1]; let user = match[1];
let appName = match[2]; let appName = match[2];
let credentials = httpd.auth_query(request.headers); let credentials = await httpd.auth_query(request.headers);
if ( if (
credentials && credentials &&
credentials.session && credentials.session &&
@ -1102,7 +1102,7 @@ async function blobHandler(request, response, blobId, uri) {
if ((match = /^\/\~(\w+)\/(\w+)$/.exec(blobId))) { if ((match = /^\/\~(\w+)\/(\w+)$/.exec(blobId))) {
let user = match[1]; let user = match[1];
let appName = match[2]; let appName = match[2];
let credentials = httpd.auth_query(request.headers); let credentials = await httpd.auth_query(request.headers);
if ( if (
credentials && credentials &&
credentials.session && credentials.session &&

View File

@ -154,8 +154,7 @@ static JSValue _database_get(JSContext* context, JSValueConst this_val, int argc
size_t length; size_t length;
const char* key = JS_ToCStringLen(context, &length, argv[0]); const char* key = JS_ToCStringLen(context, &length, argv[0]);
database_get_t* work = tf_malloc(sizeof(database_get_t) + strlen(database->id) + 1 + length + 1); database_get_t* work = tf_malloc(sizeof(database_get_t) + strlen(database->id) + 1 + length + 1);
*work = (database_get_t) *work = (database_get_t) {
{
.id = (const char*)(work + 1), .id = (const char*)(work + 1),
.key = (const char*)(work + 1) + strlen(database->id) + 1, .key = (const char*)(work + 1) + strlen(database->id) + 1,
.key_length = length, .key_length = length,
@ -226,8 +225,7 @@ static JSValue _database_set(JSContext* context, JSValueConst this_val, int argc
const char* value = JS_ToCStringLen(context, &value_length, argv[1]); const char* value = JS_ToCStringLen(context, &value_length, argv[1]);
database_set_t* work = tf_malloc(sizeof(database_set_t) + strlen(database->id) + 1 + key_length + 1 + value_length + 1); database_set_t* work = tf_malloc(sizeof(database_set_t) + strlen(database->id) + 1 + key_length + 1 + value_length + 1);
*work = (database_set_t) *work = (database_set_t) {
{
.id = (const char*)(work + 1), .id = (const char*)(work + 1),
.key = (const char*)(work + 1) + strlen(database->id) + 1, .key = (const char*)(work + 1) + strlen(database->id) + 1,
.value = (const char*)(work + 1) + strlen(database->id) + 1 + key_length + 1, .value = (const char*)(work + 1) + strlen(database->id) + 1 + key_length + 1,

View File

@ -446,6 +446,55 @@ static JSValue _httpd_set_http_redirect(JSContext* context, JSValueConst this_va
return JS_UNDEFINED; return JS_UNDEFINED;
} }
typedef struct _auth_query_work_t
{
const char* settings;
JSValue entry;
JSValue result;
JSValue promise[2];
} auth_query_work_t;
static void _httpd_auth_query_work(tf_ssb_t* ssb, void* user_data)
{
auth_query_work_t* work = user_data;
work->settings = tf_ssb_db_get_property(ssb, "core", "settings");
}
static void _httpd_auth_query_after_work(tf_ssb_t* ssb, int status, void* user_data)
{
auth_query_work_t* work = user_data;
JSContext* context = tf_ssb_get_context(ssb);
JSValue name = JS_GetPropertyStr(context, work->entry, "name");
const char* name_string = JS_ToCString(context, name);
JSValue settings_value = work->settings ? JS_ParseJSON(context, work->settings, strlen(work->settings), NULL) : JS_UNDEFINED;
JSValue out_permissions = JS_NewObject(context);
JS_SetPropertyStr(context, work->result, "permissions", out_permissions);
JSValue permissions = !JS_IsUndefined(settings_value) ? JS_GetPropertyStr(context, settings_value, "permissions") : JS_UNDEFINED;
JSValue user_permissions = !JS_IsUndefined(permissions) ? JS_GetPropertyStr(context, permissions, name_string) : JS_UNDEFINED;
int length = !JS_IsUndefined(user_permissions) ? tf_util_get_length(context, user_permissions) : 0;
for (int i = 0; i < length; i++)
{
JSValue permission = JS_GetPropertyUint32(context, user_permissions, i);
const char* permission_string = JS_ToCString(context, permission);
JS_SetPropertyStr(context, out_permissions, permission_string, JS_TRUE);
JS_FreeCString(context, permission_string);
JS_FreeValue(context, permission);
}
JSValue error = JS_Call(context, work->promise[0], JS_UNDEFINED, 1, &work->result);
JS_FreeValue(context, work->result);
tf_util_report_error(context, error);
JS_FreeValue(context, error);
JS_FreeValue(context, work->promise[0]);
JS_FreeValue(context, work->promise[1]);
JS_FreeValue(context, user_permissions);
JS_FreeValue(context, permissions);
JS_FreeValue(context, settings_value);
tf_free((void*)work->settings);
JS_FreeCString(context, name_string);
JS_FreeValue(context, name);
tf_free(work);
}
static JSValue _httpd_auth_query(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) static JSValue _httpd_auth_query(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
{ {
tf_task_t* task = tf_task_get(context); tf_task_t* task = tf_task_get(context);
@ -467,33 +516,16 @@ static JSValue _httpd_auth_query(JSContext* context, JSValueConst this_val, int
JSValue result = JS_UNDEFINED; JSValue result = JS_UNDEFINED;
if (!JS_IsUndefined(entry)) if (!JS_IsUndefined(entry))
{ {
result = JS_NewObject(context); JSValue value = JS_NewObject(context);
JS_SetPropertyStr(context, result, "session", entry); JS_SetPropertyStr(context, value, "session", entry);
JSValue out_permissions = JS_NewObject(context);
JS_SetPropertyStr(context, result, "permissions", out_permissions);
JSValue name = JS_GetPropertyStr(context, entry, "name"); auth_query_work_t* work = tf_malloc(sizeof(auth_query_work_t));
const char* name_string = JS_ToCString(context, name); *work = (auth_query_work_t) {
.entry = entry,
const char* settings = tf_ssb_db_get_property(ssb, "core", "settings"); .result = value,
JSValue settings_value = settings ? JS_ParseJSON(context, settings, strlen(settings), NULL) : JS_UNDEFINED; };
JSValue permissions = !JS_IsUndefined(settings_value) ? JS_GetPropertyStr(context, settings_value, "permissions") : JS_UNDEFINED; result = JS_NewPromiseCapability(context, work->promise);
JSValue user_permissions = !JS_IsUndefined(permissions) ? JS_GetPropertyStr(context, permissions, name_string) : JS_UNDEFINED; tf_ssb_run_work(ssb, _httpd_auth_query_work, _httpd_auth_query_after_work, work);
int length = !JS_IsUndefined(user_permissions) ? tf_util_get_length(context, user_permissions) : 0;
for (int i = 0; i < length; i++)
{
JSValue permission = JS_GetPropertyUint32(context, user_permissions, i);
const char* permission_string = JS_ToCString(context, permission);
JS_SetPropertyStr(context, out_permissions, permission_string, JS_TRUE);
JS_FreeCString(context, permission_string);
JS_FreeValue(context, permission);
}
JS_FreeValue(context, user_permissions);
JS_FreeValue(context, permissions);
JS_FreeValue(context, settings_value);
tf_free((void*)settings);
JS_FreeCString(context, name_string);
JS_FreeValue(context, name);
} }
return result; return result;
} }
@ -1315,7 +1347,6 @@ static void _httpd_endpoint_login_get_code_of_conduct_work(tf_ssb_t* ssb, void*
{ {
login_request_t* login = user_data; login_request_t* login = user_data;
login->settings = tf_ssb_db_get_property(ssb, "core", "settings"); login->settings = tf_ssb_db_get_property(ssb, "core", "settings");
} }
static void _httpd_endpoint_login_get_code_of_conduct_after_work(tf_ssb_t* ssb, int status, void* user_data) static void _httpd_endpoint_login_get_code_of_conduct_after_work(tf_ssb_t* ssb, int status, void* user_data)

View File

@ -280,8 +280,7 @@ static JSValue _tf_ssb_getIdentities(JSContext* context, JSValueConst this_val,
size_t user_length = 0; size_t user_length = 0;
const char* user = JS_ToCStringLen(context, &user_length, argv[0]); const char* user = JS_ToCStringLen(context, &user_length, argv[0]);
identities_visit_t* work = tf_malloc(sizeof(identities_visit_t) + user_length + 1); identities_visit_t* work = tf_malloc(sizeof(identities_visit_t) + user_length + 1);
*work = (identities_visit_t) *work = (identities_visit_t) {
{
.context = context, .context = context,
}; };
memcpy(work->user, user, user_length + 1); memcpy(work->user, user, user_length + 1);
@ -331,8 +330,7 @@ static JSValue _tf_ssb_getAllIdentities(JSContext* context, JSValueConst this_va
if (ssb) if (ssb)
{ {
identities_visit_t* work = tf_malloc(sizeof(identities_visit_t)); identities_visit_t* work = tf_malloc(sizeof(identities_visit_t));
*work = (identities_visit_t) *work = (identities_visit_t) {
{
.context = context, .context = context,
}; };