Compare commits
2 Commits
8ca64550e5
...
07605933dc
| Author | SHA1 | Date | |
|---|---|---|---|
| 07605933dc | |||
| 4bdc7ec616 |
13
core/core.js
13
core/core.js
@@ -352,19 +352,6 @@ async function getProcessBlob(blobId, key, options) {
|
||||
}
|
||||
};
|
||||
if (process.credentials?.permissions?.administration) {
|
||||
imports.core.globalSettingsDescriptions = async function () {
|
||||
let settings = Object.assign({}, defaultGlobalSettings());
|
||||
for (let [key, value] of Object.entries(await loadSettings())) {
|
||||
if (settings[key]) {
|
||||
settings[key].value = value;
|
||||
}
|
||||
}
|
||||
return settings;
|
||||
};
|
||||
imports.core.globalSettingsGet = async function (key) {
|
||||
let settings = await loadSettings();
|
||||
return settings?.[key];
|
||||
};
|
||||
imports.core.globalSettingsSet = async function (key, value) {
|
||||
await imports.core.permissionTest('set_global_setting');
|
||||
print('Setting', key, value);
|
||||
|
||||
169
src/api.js.c
169
src/api.js.c
@@ -555,6 +555,163 @@ static JSValue _tf_ssb_getOwnerIdentities(JSContext* context, JSValueConst this_
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef struct _settings_descriptions_get_t
|
||||
{
|
||||
const char* settings;
|
||||
JSContext* context;
|
||||
JSValue promise[2];
|
||||
} settings_descriptions_get_t;
|
||||
|
||||
static void _tf_ssb_get_settings_descriptions_work(tf_ssb_t* ssb, void* user_data)
|
||||
{
|
||||
settings_descriptions_get_t* work = user_data;
|
||||
work->settings = tf_ssb_db_get_property(ssb, "core", "settings");
|
||||
}
|
||||
|
||||
static void _tf_ssb_get_settings_descriptions_after_work(tf_ssb_t* ssb, int status, void* user_data)
|
||||
{
|
||||
settings_descriptions_get_t* work = user_data;
|
||||
JSContext* context = work->context;
|
||||
JSValue result = JS_NewObject(context);
|
||||
JSValue settings = JS_ParseJSON(context, work->settings ? work->settings : "", work->settings ? strlen(work->settings) : 0, NULL);
|
||||
const char* name;
|
||||
const char* type;
|
||||
tf_setting_kind_t kind;
|
||||
const char* description;
|
||||
for (int i = 0; tf_util_get_global_setting_by_index(i, &name, &type, &kind, &description); i++)
|
||||
{
|
||||
JSValue entry = JS_NewObject(context);
|
||||
JS_SetPropertyStr(context, entry, "type", JS_NewString(context, type));
|
||||
JS_SetPropertyStr(context, entry, "description", JS_NewString(context, description));
|
||||
switch (kind)
|
||||
{
|
||||
case k_kind_unknown:
|
||||
break;
|
||||
case k_kind_bool:
|
||||
JS_SetPropertyStr(context, entry, "default_value", JS_NewBool(context, tf_util_get_default_global_setting_bool(name)));
|
||||
break;
|
||||
case k_kind_int:
|
||||
JS_SetPropertyStr(context, entry, "default_value", JS_NewInt32(context, tf_util_get_default_global_setting_int(name)));
|
||||
break;
|
||||
case k_kind_string:
|
||||
JS_SetPropertyStr(context, entry, "default_value", JS_NewString(context, tf_util_get_default_global_setting_string(name)));
|
||||
break;
|
||||
}
|
||||
if (JS_IsObject(settings))
|
||||
{
|
||||
JS_SetPropertyStr(context, entry, "value", JS_GetPropertyStr(context, settings, name));
|
||||
}
|
||||
JS_SetPropertyStr(context, result, name, entry);
|
||||
}
|
||||
JS_FreeValue(context, settings);
|
||||
JSValue error = JS_Call(context, work->promise[0], JS_UNDEFINED, 1, &result);
|
||||
tf_util_report_error(context, error);
|
||||
JS_FreeValue(context, error);
|
||||
JS_FreeValue(context, result);
|
||||
JS_FreeValue(context, work->promise[0]);
|
||||
JS_FreeValue(context, work->promise[1]);
|
||||
tf_free((void*)work->settings);
|
||||
tf_free(work);
|
||||
}
|
||||
|
||||
static JSValue _tf_ssb_globalSettingsDescriptions(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||
{
|
||||
tf_task_t* task = tf_task_get(context);
|
||||
tf_ssb_t* ssb = tf_task_get_ssb(task);
|
||||
settings_descriptions_get_t* work = tf_malloc(sizeof(settings_descriptions_get_t));
|
||||
*work = (settings_descriptions_get_t) { .context = context };
|
||||
JSValue result = JS_NewPromiseCapability(context, work->promise);
|
||||
tf_ssb_run_work(ssb, _tf_ssb_get_settings_descriptions_work, _tf_ssb_get_settings_descriptions_after_work, work);
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef struct _settings_get_t
|
||||
{
|
||||
const char* key;
|
||||
tf_setting_kind_t kind;
|
||||
void* value;
|
||||
JSContext* context;
|
||||
JSValue promise[2];
|
||||
} settings_get_t;
|
||||
|
||||
static void _tf_ssb_settings_get_work(tf_ssb_t* ssb, void* user_data)
|
||||
{
|
||||
settings_get_t* work = user_data;
|
||||
work->kind = tf_util_get_global_setting_kind(work->key);
|
||||
switch (work->kind)
|
||||
{
|
||||
case k_kind_unknown:
|
||||
break;
|
||||
case k_kind_bool:
|
||||
{
|
||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||
bool value = false;
|
||||
tf_ssb_db_get_global_setting_bool(db, work->key, &value);
|
||||
work->value = (void*)(intptr_t)value;
|
||||
tf_ssb_release_db_reader(ssb, db);
|
||||
}
|
||||
break;
|
||||
case k_kind_int:
|
||||
{
|
||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||
int64_t value = 0;
|
||||
tf_ssb_db_get_global_setting_int64(db, work->key, &value);
|
||||
work->value = (void*)(intptr_t)value;
|
||||
tf_ssb_release_db_reader(ssb, db);
|
||||
}
|
||||
break;
|
||||
case k_kind_string:
|
||||
{
|
||||
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
|
||||
work->value = (void*)tf_ssb_db_get_global_setting_string_alloc(db, work->key);
|
||||
tf_ssb_release_db_reader(ssb, db);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _tf_ssb_settings_get_after_work(tf_ssb_t* ssb, int status, void* user_data)
|
||||
{
|
||||
settings_get_t* work = user_data;
|
||||
JSContext* context = tf_ssb_get_context(ssb);
|
||||
JSValue result = JS_UNDEFINED;
|
||||
switch (work->kind)
|
||||
{
|
||||
case k_kind_unknown:
|
||||
break;
|
||||
case k_kind_bool:
|
||||
result = work->value ? JS_TRUE : JS_FALSE;
|
||||
break;
|
||||
case k_kind_int:
|
||||
result = JS_NewInt64(context, (int64_t)(intptr_t)work->value);
|
||||
break;
|
||||
case k_kind_string:
|
||||
result = JS_NewString(context, (const char*)work->value);
|
||||
tf_free(work->value);
|
||||
break;
|
||||
}
|
||||
|
||||
JSValue error = JS_Call(context, work->promise[0], JS_UNDEFINED, 1, &result);
|
||||
tf_util_report_error(context, error);
|
||||
JS_FreeValue(context, error);
|
||||
JS_FreeValue(context, result);
|
||||
JS_FreeValue(context, work->promise[0]);
|
||||
JS_FreeValue(context, work->promise[1]);
|
||||
JS_FreeCString(context, work->key);
|
||||
tf_free(work);
|
||||
}
|
||||
|
||||
static JSValue _tf_ssb_globalSettingsGet(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||
{
|
||||
tf_task_t* task = tf_task_get(context);
|
||||
tf_ssb_t* ssb = tf_task_get_ssb(task);
|
||||
settings_get_t* work = tf_malloc(sizeof(settings_get_t));
|
||||
*work = (settings_get_t) { .context = context, .key = JS_ToCString(context, argv[0]) };
|
||||
JSValue result = JS_NewPromiseCapability(context, work->promise);
|
||||
tf_ssb_run_work(ssb, _tf_ssb_settings_get_work, _tf_ssb_settings_get_after_work, work);
|
||||
return result;
|
||||
}
|
||||
|
||||
static JSValue _tf_api_register_imports(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||
{
|
||||
JSValue imports = argv[0];
|
||||
@@ -582,6 +739,18 @@ static JSValue _tf_api_register_imports(JSContext* context, JSValueConst this_va
|
||||
JS_SetPropertyStr(context, ssb, "getOwnerIdentities", JS_NewCFunctionData(context, _tf_ssb_getOwnerIdentities, 0, 0, 1, &process));
|
||||
JS_FreeValue(context, ssb);
|
||||
|
||||
JSValue credentials = JS_GetPropertyStr(context, process, "credentials");
|
||||
JSValue permissions = JS_IsObject(credentials) ? JS_GetPropertyStr(context, credentials, "permissions") : JS_UNDEFINED;
|
||||
JSValue administration = JS_IsObject(permissions) ? JS_GetPropertyStr(context, permissions, "administration") : JS_UNDEFINED;
|
||||
if (JS_ToBool(context, administration) > 0)
|
||||
{
|
||||
JS_SetPropertyStr(context, core, "globalSettingsDescriptions", JS_NewCFunction(context, _tf_ssb_globalSettingsDescriptions, "globalSettingsDescriptions", 0));
|
||||
JS_SetPropertyStr(context, core, "globalSettingsGet", JS_NewCFunction(context, _tf_ssb_globalSettingsGet, "globalSettingsGet", 1));
|
||||
}
|
||||
JS_FreeValue(context, administration);
|
||||
JS_FreeValue(context, permissions);
|
||||
JS_FreeValue(context, credentials);
|
||||
|
||||
JS_FreeValue(context, core);
|
||||
return JS_UNDEFINED;
|
||||
}
|
||||
|
||||
26
src/ssb.db.c
26
src/ssb.db.c
@@ -2465,6 +2465,32 @@ bool tf_ssb_db_get_global_setting_string(sqlite3* db, const char* name, char* ou
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* tf_ssb_db_get_global_setting_string_alloc(sqlite3* db, const char* name)
|
||||
{
|
||||
const char* result = NULL;
|
||||
sqlite3_stmt* statement;
|
||||
if (sqlite3_prepare_v2(db, "SELECT json_extract(value, '$.' || ?) FROM properties WHERE id = 'core' AND key = 'settings'", -1, &statement, NULL) == SQLITE_OK)
|
||||
{
|
||||
if (sqlite3_bind_text(statement, 1, name, -1, NULL) == SQLITE_OK)
|
||||
{
|
||||
if (sqlite3_step(statement) == SQLITE_ROW && sqlite3_column_type(statement, 0) != SQLITE_NULL)
|
||||
{
|
||||
result = tf_strdup((const char*)sqlite3_column_text(statement, 0));
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(statement);
|
||||
}
|
||||
else
|
||||
{
|
||||
tf_printf("prepare failed: %s\n", sqlite3_errmsg(db));
|
||||
}
|
||||
if (!result)
|
||||
{
|
||||
result = tf_strdup(tf_util_get_default_global_setting_string(name));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool tf_ssb_db_set_global_setting_from_string(sqlite3* db, const char* name, char* value)
|
||||
{
|
||||
tf_setting_kind_t kind = tf_util_get_global_setting_kind(name);
|
||||
|
||||
@@ -500,6 +500,14 @@ bool tf_ssb_db_get_global_setting_int64(sqlite3* db, const char* name, int64_t*
|
||||
*/
|
||||
bool tf_ssb_db_get_global_setting_string(sqlite3* db, const char* name, char* out_value, size_t size);
|
||||
|
||||
/**
|
||||
** Get a string global setting value.
|
||||
** @param db The database.
|
||||
** @param name The setting name.
|
||||
** @return The setting if found.
|
||||
*/
|
||||
const char* tf_ssb_db_get_global_setting_string_alloc(sqlite3* db, const char* name);
|
||||
|
||||
/**
|
||||
** Set a global setting from a string representation of its value.
|
||||
** @param db The database.
|
||||
|
||||
@@ -381,6 +381,31 @@ const char* tf_util_get_default_global_setting_string(const char* name)
|
||||
return setting && setting->default_value.string_value ? setting->default_value.string_value : "";
|
||||
}
|
||||
|
||||
bool tf_util_get_global_setting_by_index(int index, const char** out_name, const char** out_type, tf_setting_kind_t* out_kind, const char** out_description)
|
||||
{
|
||||
if (index >= 0 && index < tf_countof(k_settings))
|
||||
{
|
||||
if (out_name)
|
||||
{
|
||||
*out_name = k_settings[index].name;
|
||||
}
|
||||
if (out_type)
|
||||
{
|
||||
*out_type = k_settings[index].type;
|
||||
}
|
||||
if (out_kind)
|
||||
{
|
||||
*out_kind = k_settings[index].default_value.kind;
|
||||
}
|
||||
if (out_description)
|
||||
{
|
||||
*out_description = k_settings[index].description;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static JSValue _util_defaultGlobalSettings(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv)
|
||||
{
|
||||
JSValue settings = JS_NewObject(context);
|
||||
|
||||
@@ -212,6 +212,16 @@ const char* tf_util_get_default_global_setting_string(const char* name);
|
||||
*/
|
||||
tf_setting_kind_t tf_util_get_global_setting_kind(const char* name);
|
||||
|
||||
/**
|
||||
** Get the index-th global setting.
|
||||
** @param index The index.
|
||||
** @param out_name Populated with the setting name.
|
||||
** @param out_type Populated with the setting type.
|
||||
** @param out_kind Populated with the setting kind.
|
||||
** @param out_description Populated with the setting description.
|
||||
*/
|
||||
bool tf_util_get_global_setting_by_index(int index, const char** out_name, const char** out_type, tf_setting_kind_t* out_kind, const char** out_description);
|
||||
|
||||
/**
|
||||
** Log documentation for the available settings.
|
||||
** @param line_prefix Text to prefix each line with."
|
||||
|
||||
Reference in New Issue
Block a user