Move some DB things out of httpd.

This commit is contained in:
2024-04-04 21:00:59 -04:00
parent 81d1228b92
commit c674cca482
3 changed files with 196 additions and 152 deletions

View File

@ -6,6 +6,7 @@
#include "trace.h"
#include "util.js.h"
#include "ow-crypt.h"
#include "sodium/crypto_hash_sha256.h"
#include "sodium/crypto_sign.h"
#include "sqlite3.h"
@ -1592,3 +1593,145 @@ void tf_ssb_db_forget_stored_connection(tf_ssb_t* ssb, const char* address, int
}
tf_ssb_release_db_writer(ssb, db);
}
bool tf_ssb_db_get_account_password_hash(tf_ssb_t* ssb, const char* name, char* out_password, size_t password_size)
{
bool result = false;
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db, "SELECT value ->> '$.password' FROM properties WHERE id = 'auth' AND key = 'user:' || ?", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, name, -1, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
snprintf(out_password, password_size, "%s", (const char*)sqlite3_column_text(statement, 0));
result = true;
}
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
return result;
}
bool tf_ssb_db_set_account_password(tf_ssb_t* ssb, const char* name, const char* password)
{
JSContext* context = tf_ssb_get_context(ssb);
bool result = false;
static const int k_salt_length = 12;
char buffer[16];
size_t bytes = uv_random(tf_ssb_get_loop(ssb), &(uv_random_t) { 0 }, buffer, sizeof(buffer), 0, NULL) == 0 ? sizeof(buffer) : 0;
char output[7 + 22 + 1];
char* salt = crypt_gensalt_rn("$2b$", k_salt_length, buffer, bytes, output, sizeof(output));
char hash_output[7 + 22 + 31 + 1];
char* hash = crypt_rn(password, salt, hash_output, sizeof(hash_output));
JSValue user_entry = JS_NewObject(context);
JS_SetPropertyStr(context, user_entry, "password", JS_NewString(context, hash));
JSValue user_json = JS_JSONStringify(context, user_entry, JS_NULL, JS_NULL);
size_t user_length = 0;
const char* user_string = JS_ToCStringLen(context, &user_length, user_json);
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES ('auth', 'user:' || ?, ?)", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, name, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, user_string, user_length, NULL) == SQLITE_OK)
{
result = sqlite3_step(statement) == SQLITE_DONE;
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_writer(ssb, db);
JS_FreeCString(context, user_string);
JS_FreeValue(context, user_json);
JS_FreeValue(context, user_entry);
return result;
}
bool tf_ssb_db_register_account(tf_ssb_t* ssb, const char* name, const char* password)
{
bool result = false;
JSContext* context = tf_ssb_get_context(ssb);
JSValue users_array = JS_UNDEFINED;
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db, "SELECT value FROM properties WHERE id = 'auth' AND key = 'users'", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
users_array = JS_ParseJSON(context, (const char*)sqlite3_column_text(statement, 0), sqlite3_column_bytes(statement, 0), NULL);
}
sqlite3_finalize(statement);
}
if (JS_IsUndefined(users_array))
{
users_array = JS_NewArray(context);
}
int length = tf_util_get_length(context, users_array);
JS_SetPropertyUint32(context, users_array, length, JS_NewString(context, name));
JSValue json = JS_JSONStringify(context, users_array, JS_NULL, JS_NULL);
JS_FreeValue(context, users_array);
size_t value_length = 0;
const char* value = JS_ToCStringLen(context, &value_length, json);
if (sqlite3_prepare(db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES ('auth', 'users', ?)", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, value, value_length, NULL) == SQLITE_OK)
{
result = sqlite3_step(statement) == SQLITE_DONE;
}
sqlite3_finalize(statement);
}
JS_FreeCString(context, value);
JS_FreeValue(context, json);
tf_ssb_release_db_writer(ssb, db);
result = result && tf_ssb_db_set_account_password(ssb, name, password);
return result;
}
const char* tf_ssb_db_get_property(tf_ssb_t* ssb, const char* id, const char* key)
{
char* result = NULL;
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db, "SELECT value FROM properties WHERE id = ? AND key = ?", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, key, -1, NULL) == SQLITE_OK)
{
if (sqlite3_step(statement) == SQLITE_ROW)
{
size_t length = sqlite3_column_bytes(statement, 0);
result = tf_malloc(length + 1);
memcpy(result, sqlite3_column_text(statement, 0), length);
result[length] = '\0';
}
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_reader(ssb, db);
return result;
}
bool tf_ssb_db_set_property(tf_ssb_t* ssb, const char* id, const char* key, const char* value)
{
bool result = false;
sqlite3* db = tf_ssb_acquire_db_writer(ssb);
sqlite3_stmt* statement = NULL;
if (sqlite3_prepare(db, "INSERT OR REPLACE INTO properties (id, key, value) VALUES (?, ?, ?)", -1, &statement, NULL) == SQLITE_OK)
{
if (sqlite3_bind_text(statement, 1, id, -1, NULL) == SQLITE_OK && sqlite3_bind_text(statement, 2, key, -1, NULL) == SQLITE_OK &&
sqlite3_bind_text(statement, 3, value, -1, NULL) == SQLITE_OK)
{
result = sqlite3_step(statement) == SQLITE_DONE;
}
sqlite3_finalize(statement);
}
tf_ssb_release_db_writer(ssb, db);
return result;
}