v0.3.15 - How can administration take so long
This commit is contained in:
160
src/config.c
160
src/config.c
@@ -342,7 +342,7 @@ int store_config_event_in_database(const cJSON* event) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Insert or replace the configuration event (kind 33334 is replaceable)
|
||||
// Insert or replace the configuration event
|
||||
const char* sql = "INSERT OR REPLACE INTO events (id, pubkey, created_at, kind, event_type, content, sig, tags) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
|
||||
sqlite3_stmt* stmt;
|
||||
|
||||
@@ -357,7 +357,7 @@ int store_config_event_in_database(const cJSON* event) {
|
||||
sqlite3_bind_text(stmt, 2, cJSON_GetStringValue(pubkey_obj), -1, SQLITE_STATIC);
|
||||
sqlite3_bind_int64(stmt, 3, (sqlite3_int64)cJSON_GetNumberValue(created_at_obj));
|
||||
sqlite3_bind_int(stmt, 4, (int)cJSON_GetNumberValue(kind_obj));
|
||||
sqlite3_bind_text(stmt, 5, "addressable", -1, SQLITE_STATIC); // kind 33334 is addressable
|
||||
sqlite3_bind_text(stmt, 5, "regular", -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 6, cJSON_GetStringValue(content_obj), -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 7, cJSON_GetStringValue(sig_obj), -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 8, tags_str, -1, SQLITE_TRANSIENT);
|
||||
@@ -384,26 +384,9 @@ cJSON* load_config_event_from_database(const char* relay_pubkey) {
|
||||
sqlite3_stmt* stmt;
|
||||
int rc;
|
||||
|
||||
// Try to get admin pubkey from cache, otherwise find the most recent kind 33334 event
|
||||
const char* admin_pubkey = get_admin_pubkey_cached();
|
||||
if (admin_pubkey && strlen(admin_pubkey) > 0) {
|
||||
sql = "SELECT id, pubkey, created_at, kind, content, sig, tags FROM events WHERE kind = 33334 AND pubkey = ? ORDER BY created_at DESC LIMIT 1";
|
||||
rc = sqlite3_prepare_v2(g_db, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK) {
|
||||
log_error("Failed to prepare configuration event query");
|
||||
return NULL;
|
||||
}
|
||||
sqlite3_bind_text(stmt, 1, admin_pubkey, -1, SQLITE_STATIC);
|
||||
} else {
|
||||
// During existing relay startup, we don't know the admin pubkey yet
|
||||
// Look for any kind 33334 configuration event (should only be one per relay)
|
||||
sql = "SELECT id, pubkey, created_at, kind, content, sig, tags FROM events WHERE kind = 33334 ORDER BY created_at DESC LIMIT 1";
|
||||
rc = sqlite3_prepare_v2(g_db, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK) {
|
||||
log_error("Failed to prepare configuration event query");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
// Configuration is now managed through config table, not events
|
||||
log_info("Configuration events are no longer stored in events table");
|
||||
return NULL;
|
||||
|
||||
cJSON* event = NULL;
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
@@ -937,7 +920,7 @@ cJSON* create_default_config_event(const unsigned char* admin_privkey_bytes,
|
||||
|
||||
// Create and sign event using nostr_core_lib
|
||||
cJSON* event = nostr_create_and_sign_event(
|
||||
33334, // kind
|
||||
23455, // kind
|
||||
"C Nostr Relay Configuration", // content
|
||||
tags, // tags
|
||||
admin_privkey_bytes, // private key bytes for signing
|
||||
@@ -1614,7 +1597,7 @@ int process_configuration_event(const cJSON* event) {
|
||||
cJSON* kind_obj = cJSON_GetObjectItem(event, "kind");
|
||||
cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
|
||||
|
||||
if (!kind_obj || cJSON_GetNumberValue(kind_obj) != 33334) {
|
||||
if (!kind_obj || (cJSON_GetNumberValue(kind_obj) != 23455 && cJSON_GetNumberValue(kind_obj) != 23456)) {
|
||||
log_error("Invalid event kind for configuration");
|
||||
return -1;
|
||||
}
|
||||
@@ -1775,7 +1758,7 @@ int apply_runtime_config_handlers(const cJSON* old_config, const cJSON* new_conf
|
||||
if (handlers_applied > 0) {
|
||||
char audit_msg[512];
|
||||
snprintf(audit_msg, sizeof(audit_msg),
|
||||
"Configuration updated via kind 33334 event - %d system components reinitialized",
|
||||
"Configuration updated via admin event - %d system components reinitialized",
|
||||
handlers_applied);
|
||||
log_success(audit_msg);
|
||||
} else {
|
||||
@@ -1832,7 +1815,7 @@ int apply_configuration_from_event(const cJSON* event) {
|
||||
// REAL-TIME EVENT HANDLER (called from main.c)
|
||||
// ================================
|
||||
|
||||
// Handle kind 33334 configuration events received via WebSocket
|
||||
// Handle configuration events received via WebSocket
|
||||
int handle_configuration_event(cJSON* event, char* error_message, size_t error_size) {
|
||||
if (!event) {
|
||||
snprintf(error_message, error_size, "invalid: null configuration event");
|
||||
@@ -2121,12 +2104,6 @@ int process_admin_event_in_config(cJSON* event, char* error_message, size_t erro
|
||||
case 23456: // New ephemeral auth rules management
|
||||
log_info("DEBUG: Routing to process_admin_auth_event (kind 23456)");
|
||||
return process_admin_auth_event(event, error_message, error_size, wsi);
|
||||
case 33334: // Legacy addressable config events (backward compatibility)
|
||||
log_info("DEBUG: Routing to process_admin_config_event (legacy kind 33334)");
|
||||
return process_admin_config_event(event, error_message, error_size);
|
||||
case 33335: // Legacy addressable auth events (backward compatibility)
|
||||
log_info("DEBUG: Routing to process_admin_auth_event (legacy kind 33335)");
|
||||
return process_admin_auth_event(event, error_message, error_size, wsi);
|
||||
default:
|
||||
log_error("DEBUG: Unsupported admin event kind");
|
||||
printf(" Unsupported kind: %d\n", kind);
|
||||
@@ -2135,7 +2112,7 @@ int process_admin_event_in_config(cJSON* event, char* error_message, size_t erro
|
||||
}
|
||||
}
|
||||
|
||||
// Handle Kind 23455 configuration management events and legacy Kind 33334
|
||||
// Handle Kind 23455 configuration management events
|
||||
int process_admin_config_event(cJSON* event, char* error_message, size_t error_size) {
|
||||
cJSON* kind_obj = cJSON_GetObjectItem(event, "kind");
|
||||
int kind = kind_obj ? (int)cJSON_GetNumberValue(kind_obj) : 0;
|
||||
@@ -2211,10 +2188,6 @@ int process_admin_config_event(cJSON* event, char* error_message, size_t error_s
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip relay identifier tag (only for legacy addressable events)
|
||||
if (kind == 33334 && strcmp(key, "d") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Update configuration in table
|
||||
if (update_config_in_table(key, value) == 0) {
|
||||
@@ -2238,7 +2211,7 @@ int process_admin_config_event(cJSON* event, char* error_message, size_t error_s
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle Kind 23456 auth rules management and legacy Kind 33335
|
||||
// Handle Kind 23456 auth rules management
|
||||
int process_admin_auth_event(cJSON* event, char* error_message, size_t error_size, struct lws* wsi) {
|
||||
log_info("DEBUG: Entering process_admin_auth_event()");
|
||||
|
||||
@@ -2267,13 +2240,6 @@ int process_admin_auth_event(cJSON* event, char* error_message, size_t error_siz
|
||||
return handle_kind_23456_unified(event, error_message, error_size, wsi);
|
||||
}
|
||||
|
||||
// Legacy Kind 33335 events use the unified handler as well
|
||||
if (kind == 33335) {
|
||||
log_info("DEBUG: Routing legacy Kind 33335 to unified handler");
|
||||
// For legacy events, we still use the unified handler but may need special processing
|
||||
// The unified handler already supports all the functionality
|
||||
return handle_kind_23456_unified(event, error_message, error_size, wsi);
|
||||
}
|
||||
|
||||
log_error("DEBUG: Unsupported auth event kind in process_admin_auth_event");
|
||||
printf(" Unsupported kind: %d\n", kind);
|
||||
@@ -3072,6 +3038,85 @@ int handle_system_command_unified(cJSON* event, const char* command, char* error
|
||||
snprintf(error_message, error_size, "failed to send clear auth rules response");
|
||||
return -1;
|
||||
}
|
||||
else if (strcmp(command, "delete_auth_rule") == 0) {
|
||||
// Get rule parameters from tags
|
||||
const char* rule_type = get_tag_value(event, "system_command", 2);
|
||||
const char* pattern_type = get_tag_value(event, "system_command", 3);
|
||||
const char* pattern_value = get_tag_value(event, "system_command", 4);
|
||||
|
||||
if (!rule_type || !pattern_type || !pattern_value) {
|
||||
snprintf(error_message, error_size, "invalid: delete_auth_rule requires rule_type, pattern_type, and pattern_value");
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_info("Processing delete auth rule command");
|
||||
printf(" Rule type: %s\n", rule_type);
|
||||
printf(" Pattern type: %s\n", pattern_type);
|
||||
printf(" Pattern value: %s\n", pattern_value);
|
||||
|
||||
// Check if rule exists before deletion
|
||||
const char* check_sql = "SELECT COUNT(*) FROM auth_rules WHERE rule_type = ? AND pattern_type = ? AND pattern_value = ?";
|
||||
sqlite3_stmt* check_stmt;
|
||||
|
||||
int check_rc = sqlite3_prepare_v2(g_db, check_sql, -1, &check_stmt, NULL);
|
||||
if (check_rc != SQLITE_OK) {
|
||||
snprintf(error_message, error_size, "failed to prepare rule existence check");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sqlite3_bind_text(check_stmt, 1, rule_type, -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(check_stmt, 2, pattern_type, -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(check_stmt, 3, pattern_value, -1, SQLITE_STATIC);
|
||||
|
||||
int rule_exists = 0;
|
||||
if (sqlite3_step(check_stmt) == SQLITE_ROW) {
|
||||
rule_exists = sqlite3_column_int(check_stmt, 0) > 0;
|
||||
}
|
||||
sqlite3_finalize(check_stmt);
|
||||
|
||||
if (!rule_exists) {
|
||||
snprintf(error_message, error_size, "error: auth rule not found");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Delete the specific auth rule
|
||||
if (remove_auth_rule_from_config(rule_type, pattern_type, pattern_value) != 0) {
|
||||
snprintf(error_message, error_size, "failed to delete auth rule from database");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Build response
|
||||
cJSON* response = cJSON_CreateObject();
|
||||
cJSON_AddStringToObject(response, "command", "delete_auth_rule");
|
||||
cJSON_AddStringToObject(response, "rule_type", rule_type);
|
||||
cJSON_AddStringToObject(response, "pattern_type", pattern_type);
|
||||
cJSON_AddStringToObject(response, "pattern_value", pattern_value);
|
||||
cJSON_AddStringToObject(response, "status", "success");
|
||||
cJSON_AddNumberToObject(response, "timestamp", (double)time(NULL));
|
||||
|
||||
printf("Deleted auth rule: %s %s:%s\n", rule_type, pattern_type, pattern_value);
|
||||
|
||||
// Get admin pubkey from event for response
|
||||
cJSON* pubkey_obj = cJSON_GetObjectItem(event, "pubkey");
|
||||
const char* admin_pubkey = pubkey_obj ? cJSON_GetStringValue(pubkey_obj) : NULL;
|
||||
|
||||
if (!admin_pubkey) {
|
||||
cJSON_Delete(response);
|
||||
snprintf(error_message, error_size, "missing admin pubkey for response");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Send response as signed kind 23457 event
|
||||
if (send_admin_response_event(response, admin_pubkey, wsi) == 0) {
|
||||
log_success("Delete auth rule command completed successfully with signed response");
|
||||
cJSON_Delete(response);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cJSON_Delete(response);
|
||||
snprintf(error_message, error_size, "failed to send delete auth rule response");
|
||||
return -1;
|
||||
}
|
||||
else if (strcmp(command, "system_status") == 0) {
|
||||
// Build system status response
|
||||
cJSON* response = cJSON_CreateObject();
|
||||
@@ -3535,7 +3580,7 @@ int process_startup_config_event(const cJSON* event) {
|
||||
|
||||
// Validate event structure first
|
||||
cJSON* kind_obj = cJSON_GetObjectItem(event, "kind");
|
||||
if (!kind_obj || cJSON_GetNumberValue(kind_obj) != 33334) {
|
||||
if (!kind_obj || cJSON_GetNumberValue(kind_obj) != 23455) {
|
||||
log_error("Invalid event kind for startup configuration");
|
||||
return -1;
|
||||
}
|
||||
@@ -3633,14 +3678,14 @@ int process_startup_config_event_with_fallback(const cJSON* event) {
|
||||
// DYNAMIC EVENT GENERATION FROM CONFIG TABLE
|
||||
// ================================
|
||||
|
||||
// Generate synthetic kind 33334 configuration event from current config table data
|
||||
// Generate synthetic configuration event from current config table data
|
||||
cJSON* generate_config_event_from_table(void) {
|
||||
if (!g_db) {
|
||||
log_error("Database not available for config event generation");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
log_info("Generating synthetic kind 33334 event from config table...");
|
||||
log_info("Generating synthetic configuration event from config table...");
|
||||
|
||||
// Get relay pubkey for event generation
|
||||
const char* relay_pubkey = get_config_value("relay_pubkey");
|
||||
@@ -3664,7 +3709,7 @@ cJSON* generate_config_event_from_table(void) {
|
||||
cJSON_AddStringToObject(event, "id", "synthetic_config_event_id");
|
||||
cJSON_AddStringToObject(event, "pubkey", relay_pubkey); // Use relay pubkey as event author
|
||||
cJSON_AddNumberToObject(event, "created_at", (double)time(NULL));
|
||||
cJSON_AddNumberToObject(event, "kind", 33334);
|
||||
cJSON_AddNumberToObject(event, "kind", 23455);
|
||||
cJSON_AddStringToObject(event, "content", "C Nostr Relay Configuration");
|
||||
cJSON_AddStringToObject(event, "sig", "synthetic_signature");
|
||||
|
||||
@@ -3724,13 +3769,13 @@ cJSON* generate_config_event_from_table(void) {
|
||||
|
||||
char success_msg[256];
|
||||
snprintf(success_msg, sizeof(success_msg),
|
||||
"Generated synthetic kind 33334 event with %d configuration items", config_items_added);
|
||||
"Generated synthetic configuration event with %d configuration items", config_items_added);
|
||||
log_success(success_msg);
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
// Check if a REQ filter requests kind 33334 events
|
||||
// Check if a REQ filter requests configuration events
|
||||
int req_filter_requests_config_events(const cJSON* filter) {
|
||||
if (!filter || !cJSON_IsObject(filter)) {
|
||||
return 0;
|
||||
@@ -3741,10 +3786,11 @@ int req_filter_requests_config_events(const cJSON* filter) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Check if kinds array contains 33334
|
||||
// Check if kinds array contains configuration event kinds
|
||||
cJSON* kind_item = NULL;
|
||||
cJSON_ArrayForEach(kind_item, kinds) {
|
||||
if (cJSON_IsNumber(kind_item) && (int)cJSON_GetNumberValue(kind_item) == 33334) {
|
||||
int kind_val = (int)cJSON_GetNumberValue(kind_item);
|
||||
if (cJSON_IsNumber(kind_item) && (kind_val == 23455 || kind_val == 23456)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -3758,7 +3804,7 @@ cJSON* generate_synthetic_config_event_for_subscription(const char* sub_id, cons
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check if any filter requests kind 33334
|
||||
// Check if any filter requests configuration events
|
||||
int requests_config = 0;
|
||||
|
||||
if (cJSON_IsArray(filters)) {
|
||||
@@ -3778,7 +3824,7 @@ cJSON* generate_synthetic_config_event_for_subscription(const char* sub_id, cons
|
||||
return NULL;
|
||||
}
|
||||
|
||||
log_info("Generating synthetic kind 33334 event for subscription");
|
||||
log_info("Generating synthetic configuration event for subscription");
|
||||
|
||||
// Generate synthetic config event from table
|
||||
cJSON* config_event = generate_config_event_from_table();
|
||||
@@ -3793,12 +3839,12 @@ cJSON* generate_synthetic_config_event_for_subscription(const char* sub_id, cons
|
||||
cJSON_AddItemToArray(event_msg, cJSON_CreateString(sub_id));
|
||||
cJSON_AddItemToArray(event_msg, config_event);
|
||||
|
||||
log_success("Generated synthetic kind 33334 configuration event message");
|
||||
log_success("Generated synthetic configuration event message");
|
||||
return event_msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a synthetic kind 33334 configuration event from config table data
|
||||
* Generate a synthetic configuration event from config table data
|
||||
* This allows WebSocket clients to fetch configuration via REQ messages
|
||||
* Returns JSON string that must be freed by caller
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user