diff --git a/relay.pid b/relay.pid index eac4312..ecc7563 100644 --- a/relay.pid +++ b/relay.pid @@ -1 +1 @@ -1643897 +1661694 diff --git a/src/config.c b/src/config.c index cc234cf..a9e4154 100644 --- a/src/config.c +++ b/src/config.c @@ -30,6 +30,7 @@ #include #include #include +#include #include // External database connection (from main.c) @@ -388,7 +389,35 @@ int is_nip42_auth_globally_required(void) { // FIRST-TIME STARTUP FUNCTIONS // ================================ -int is_first_time_startup(void) { +int is_first_time_startup(const char* db_connection_target) { +#ifdef DB_BACKEND_POSTGRES + // PostgreSQL mode: determine first-time startup from existing config rows, + // not from local .db files. + void* temp_conn = NULL; + if (db_open_worker_connection(db_connection_target, &temp_conn) != DB_OK || !temp_conn) { + DEBUG_WARN("PostgreSQL startup detection: unable to open database connection; assuming first-time startup"); + return 1; + } + + int config_table_exists = 0; + if (db_table_exists("config", &config_table_exists) != DB_OK || !config_table_exists) { + db_close_worker_connection(temp_conn); + return 1; + } + + char* relay_pubkey = db_get_config_value_dup("relay_pubkey"); + char* admin_pubkey = db_get_config_value_dup("admin_pubkey"); + + int has_relay_pubkey = (relay_pubkey && strlen(relay_pubkey) == 64); + int has_admin_pubkey = (admin_pubkey && strlen(admin_pubkey) > 0); + + if (relay_pubkey) free(relay_pubkey); + if (admin_pubkey) free(admin_pubkey); + + db_close_worker_connection(temp_conn); + return (has_relay_pubkey && has_admin_pubkey) ? 0 : 1; +#else + (void)db_connection_target; char** existing_files = find_existing_db_files(); if (existing_files) { // Free the array @@ -399,6 +428,7 @@ int is_first_time_startup(void) { return 0; // Not first time } return 1; // First time +#endif } // ================================ @@ -692,6 +722,13 @@ int first_time_startup_sequence(const cli_options_t* cli_options, char* admin_pu char* saveptr = NULL; char* token = strtok_r(keys_copy, ",", &saveptr); while (token) { + // Trim leading/trailing whitespace from each token + while (*token && isspace((unsigned char)*token)) token++; + char* end = token + strlen(token); + while (end > token && isspace((unsigned char)*(end - 1))) { + *(--end) = '\0'; + } + if (strlen(token) != ADMIN_PUBKEY_HEX_LEN) { free(keys_copy); DEBUG_ERROR("Invalid admin public key format - each pubkey must be 64 hex characters"); @@ -4839,6 +4876,20 @@ static int is_valid_hex_pubkey(const char* pubkey) { return 1; } +static void strip_whitespace_in_place(char* s) { + if (!s) return; + + char* src = s; + char* dst = s; + while (*src) { + if (!isspace((unsigned char)*src)) { + *dst++ = *src; + } + src++; + } + *dst = '\0'; +} + int reload_admin_pubkeys_cache(void) { const char* admin_pubkeys_str = get_config_value_from_table("admin_pubkey"); if (!admin_pubkeys_str) { @@ -4855,6 +4906,9 @@ int reload_admin_pubkeys_cache(void) { return -1; } + // Accept operator/user formatting like "key1, key2" by removing all whitespace. + strip_whitespace_in_place(list_copy); + char parsed_pubkeys[MAX_ADMIN_PUBKEYS][ADMIN_PUBKEY_HEX_LEN + 1] = {{0}}; int parsed_count = 0; diff --git a/src/config.h b/src/config.h index 21c2c1b..5043a25 100644 --- a/src/config.h +++ b/src/config.h @@ -70,7 +70,7 @@ int get_config_int(const char* key, int default_value); int get_config_bool(const char* key, int default_value); // First-time startup functions -int is_first_time_startup(void); +int is_first_time_startup(const char* db_connection_target); int first_time_startup_sequence(const cli_options_t* cli_options, char* admin_pubkey_out, char* relay_pubkey_out, char* relay_privkey_out); int startup_existing_relay(const char* relay_pubkey, const cli_options_t* cli_options); diff --git a/src/main.c b/src/main.c index 0fd2096..496e021 100644 --- a/src/main.c +++ b/src/main.c @@ -2054,6 +2054,19 @@ int main(int argc, char* argv[]) { char* saveptr = NULL; char* token = strtok_r(keys_copy, ",", &saveptr); while (token) { + // Trim leading/trailing whitespace in each comma-separated token + while (*token == ' ' || *token == '\t' || *token == '\n' || *token == '\r') token++; + char* token_end = token + strlen(token); + while (token_end > token && + (token_end[-1] == ' ' || token_end[-1] == '\t' || token_end[-1] == '\n' || token_end[-1] == '\r')) { + *--token_end = '\0'; + } + + if (*token == '\0') { + token = strtok_r(NULL, ",", &saveptr); + continue; + } + char decoded_key[65] = {0}; unsigned char pubkey_bytes[32]; @@ -2263,7 +2276,13 @@ int main(int argc, char* argv[]) { DEBUG_INFO("Nostr callback logging initialized at level %d", (int)nostr_level); // Check if this is first-time startup or existing relay - if (is_first_time_startup()) { + char startup_db_target[1024] = {0}; + const char* startup_probe_target = NULL; + if (build_db_connection_override(&cli_options, startup_db_target, sizeof(startup_db_target))) { + startup_probe_target = startup_db_target; + } + + if (is_first_time_startup(startup_probe_target)) { DEBUG_LOG("First-time startup detected"); // Initialize event-based configuration system @@ -2350,14 +2369,38 @@ int main(int argc, char* argv[]) { } else { + // Initialize event-based configuration system + if (init_configuration_system(NULL, NULL) != 0) { + DEBUG_ERROR("Failed to initialize event-based configuration system"); + nostr_cleanup(); + return 1; + } + +#ifdef DB_BACKEND_POSTGRES + // PostgreSQL existing relay: use configured connection target directly. + DEBUG_TRACE("Initializing existing PostgreSQL database"); + char db_connection_override[1024] = {0}; + const char* init_db_target = g_database_path; + if (build_db_connection_override(&cli_options, db_connection_override, sizeof(db_connection_override))) { + init_db_target = db_connection_override; + } + if (init_database(init_db_target) != 0) { + DEBUG_ERROR("Failed to initialize existing PostgreSQL database"); + cleanup_configuration_system(); + nostr_cleanup(); + return 1; + } + DEBUG_LOG("Existing PostgreSQL database initialized"); +#else // Find existing database file char** existing_files = find_existing_db_files(); if (!existing_files || !existing_files[0]) { DEBUG_ERROR("No existing relay database found"); + cleanup_configuration_system(); nostr_cleanup(); return 1; } - + // Extract relay pubkey from filename char* relay_pubkey = extract_pubkey_from_filename(existing_files[0]); if (!relay_pubkey) { @@ -2367,22 +2410,11 @@ int main(int argc, char* argv[]) { free(existing_files[i]); } free(existing_files); + cleanup_configuration_system(); nostr_cleanup(); return 1; } - - // Initialize event-based configuration system - if (init_configuration_system(NULL, NULL) != 0) { - DEBUG_ERROR("Failed to initialize event-based configuration system"); - free(relay_pubkey); - for (int i = 0; existing_files[i]; i++) { - free(existing_files[i]); - } - free(existing_files); - nostr_cleanup(); - return 1; - } - + // Setup existing relay FIRST (sets database path) if (startup_existing_relay(relay_pubkey, &cli_options) != 0) { DEBUG_ERROR("Failed to setup existing relay"); @@ -2416,15 +2448,18 @@ int main(int argc, char* argv[]) { } DEBUG_LOG("Existing database initialized"); + // Free memory + free(relay_pubkey); + for (int i = 0; existing_files[i]; i++) { + free(existing_files[i]); + } + free(existing_files); +#endif + // Keep relay_version in sync with the compiled binary version on every startup if (update_config_in_table("relay_version", CRELAY_VERSION) != 0) { DEBUG_ERROR("Failed to synchronize relay_version with compiled CRELAY_VERSION"); cleanup_configuration_system(); - free(relay_pubkey); - for (int i = 0; existing_files[i]; i++) { - free(existing_files[i]); - } - free(existing_files); nostr_cleanup(); close_database(); return 1; @@ -2435,11 +2470,6 @@ int main(int argc, char* argv[]) { if (apply_cli_overrides_atomic(&cli_options) != 0) { DEBUG_ERROR("Failed to apply CLI overrides for existing relay"); cleanup_configuration_system(); - free(relay_pubkey); - for (int i = 0; existing_files[i]; i++) { - free(existing_files[i]); - } - free(existing_files); nostr_cleanup(); close_database(); return 1; @@ -2452,13 +2482,6 @@ int main(int argc, char* argv[]) { DEBUG_LOG("Config table row count after init_database(): %d", row_count); } } - - // Free memory - free(relay_pubkey); - for (int i = 0; existing_files[i]; i++) { - free(existing_files[i]); - } - free(existing_files); } // Verify database is now available diff --git a/src/main.h b/src/main.h index 70fbed4..5cb12d1 100644 --- a/src/main.h +++ b/src/main.h @@ -13,8 +13,8 @@ // Using CRELAY_ prefix to avoid conflicts with nostr_core_lib VERSION macros #define CRELAY_VERSION_MAJOR 2 #define CRELAY_VERSION_MINOR 1 -#define CRELAY_VERSION_PATCH 12 -#define CRELAY_VERSION "v2.1.12" +#define CRELAY_VERSION_PATCH 13 +#define CRELAY_VERSION "v2.1.13" // Relay metadata (authoritative source for NIP-11 information) #define RELAY_NAME "C-Relay-PG"