v2.1.13 - Fix PostgreSQL startup detection for existing relays and make admin_pubkey parsing whitespace-tolerant

This commit is contained in:
Laan Tungir
2026-04-03 16:36:56 -04:00
parent fd3efdd01f
commit c02ae2be5b
5 changed files with 114 additions and 37 deletions
+1 -1
View File
@@ -1 +1 @@
1643897
1661694
+55 -1
View File
@@ -30,6 +30,7 @@
#include <sys/stat.h>
#include <errno.h>
#include <signal.h>
#include <ctype.h>
#include <libwebsockets.h>
// 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;
+1 -1
View File
@@ -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);
+55 -32
View File
@@ -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
+2 -2
View File
@@ -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"