v0.3.11 - Working on admin api
This commit is contained in:
586
src/config.c
586
src/config.c
@@ -73,6 +73,16 @@ int is_config_table_ready(void);
|
||||
int migrate_config_from_events_to_table(void);
|
||||
int populate_config_table_from_event(const cJSON* event);
|
||||
|
||||
// Forward declarations for admin API query handlers
|
||||
int handle_config_list_keys_query(cJSON* event, char* error_message, size_t error_size);
|
||||
int handle_config_get_current_query(cJSON* event, char* error_message, size_t error_size);
|
||||
int handle_auth_list_all_query(cJSON* event, char* error_message, size_t error_size);
|
||||
int handle_auth_whitelist_query(cJSON* event, char* error_message, size_t error_size);
|
||||
int handle_auth_blacklist_query(cJSON* event, char* error_message, size_t error_size);
|
||||
int handle_auth_pattern_check_query(cJSON* event, char* error_message, size_t error_size);
|
||||
int handle_clear_all_auth_rules_command(cJSON* event, char* error_message, size_t error_size);
|
||||
int handle_system_status_query(cJSON* event, char* error_message, size_t error_size);
|
||||
|
||||
// Current configuration cache
|
||||
static cJSON* g_current_config = NULL;
|
||||
|
||||
@@ -2055,7 +2065,7 @@ int add_pubkeys_to_config_table(void) {
|
||||
// ADMIN EVENT PROCESSING FUNCTIONS
|
||||
// ================================
|
||||
|
||||
// Process admin events (moved from main.c)
|
||||
// Process admin events (updated for new Kind 23455/23456)
|
||||
int process_admin_event_in_config(cJSON* event, char* error_message, size_t error_size) {
|
||||
cJSON* kind_obj = cJSON_GetObjectItem(event, "kind");
|
||||
if (!kind_obj || !cJSON_IsNumber(kind_obj)) {
|
||||
@@ -2081,26 +2091,64 @@ int process_admin_event_in_config(cJSON* event, char* error_message, size_t erro
|
||||
int kind = (int)cJSON_GetNumberValue(kind_obj);
|
||||
|
||||
switch (kind) {
|
||||
case 33334:
|
||||
case 23455: // New ephemeral configuration management
|
||||
return process_admin_config_event(event, error_message, error_size);
|
||||
case 33335:
|
||||
case 23456: // New ephemeral auth rules management
|
||||
return process_admin_auth_event(event, error_message, error_size);
|
||||
case 33334: // Legacy addressable config events (backward compatibility)
|
||||
return process_admin_config_event(event, error_message, error_size);
|
||||
case 33335: // Legacy addressable auth events (backward compatibility)
|
||||
return process_admin_auth_event(event, error_message, error_size);
|
||||
default:
|
||||
snprintf(error_message, error_size, "invalid: unsupported admin event kind");
|
||||
snprintf(error_message, error_size, "invalid: unsupported admin event kind %d", kind);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle kind 33334 config events
|
||||
// Handle Kind 23455 configuration management events and legacy Kind 33334
|
||||
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;
|
||||
|
||||
// Parse content for action commands
|
||||
cJSON* content_obj = cJSON_GetObjectItem(event, "content");
|
||||
const char* content = content_obj ? cJSON_GetStringValue(content_obj) : "";
|
||||
|
||||
// Check if this is a query command
|
||||
cJSON* content_json = cJSON_Parse(content);
|
||||
char action_buffer[32] = "set"; // default action
|
||||
const char* action = action_buffer;
|
||||
|
||||
if (content_json) {
|
||||
cJSON* action_obj = cJSON_GetObjectItem(content_json, "action");
|
||||
if (action_obj && cJSON_IsString(action_obj)) {
|
||||
const char* action_str = cJSON_GetStringValue(action_obj);
|
||||
if (action_str) {
|
||||
strncpy(action_buffer, action_str, sizeof(action_buffer) - 1);
|
||||
action_buffer[sizeof(action_buffer) - 1] = '\0';
|
||||
}
|
||||
}
|
||||
cJSON_Delete(content_json);
|
||||
}
|
||||
|
||||
log_info("Processing admin configuration event");
|
||||
printf(" Kind: %d, Action: %s\n", kind, action);
|
||||
|
||||
// Handle query commands
|
||||
if (strcmp(action, "list_config_keys") == 0) {
|
||||
return handle_config_list_keys_query(event, error_message, error_size);
|
||||
}
|
||||
if (strcmp(action, "get_current_config") == 0) {
|
||||
return handle_config_get_current_query(event, error_message, error_size);
|
||||
}
|
||||
|
||||
// Handle configuration updates (set action)
|
||||
cJSON* tags_obj = cJSON_GetObjectItem(event, "tags");
|
||||
if (!tags_obj || !cJSON_IsArray(tags_obj)) {
|
||||
snprintf(error_message, error_size, "invalid: configuration event must have tags");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Config table should already exist from embedded schema
|
||||
|
||||
// Begin transaction for atomic config updates
|
||||
int rc = sqlite3_exec(g_db, "BEGIN IMMEDIATE TRANSACTION", NULL, NULL, NULL);
|
||||
if (rc != SQLITE_OK) {
|
||||
@@ -2127,8 +2175,8 @@ int process_admin_config_event(cJSON* event, char* error_message, size_t error_s
|
||||
const char* key = cJSON_GetStringValue(tag_name);
|
||||
const char* value = cJSON_GetStringValue(tag_value);
|
||||
|
||||
// Skip relay identifier tag
|
||||
if (strcmp(key, "d") == 0) {
|
||||
// Skip relay identifier tag (only for legacy addressable events)
|
||||
if (kind == 33334 && strcmp(key, "d") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2154,35 +2202,21 @@ int process_admin_config_event(cJSON* event, char* error_message, size_t error_s
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle kind 33335 auth rule events
|
||||
// Handle Kind 23456 auth rules management and legacy Kind 33335
|
||||
int process_admin_auth_event(cJSON* event, char* error_message, size_t error_size) {
|
||||
log_info("=== SERVER-SIDE AUTH RULE EVENT DEBUG ===");
|
||||
cJSON* kind_obj = cJSON_GetObjectItem(event, "kind");
|
||||
int kind = kind_obj ? (int)cJSON_GetNumberValue(kind_obj) : 0;
|
||||
|
||||
// Print the entire received event for debugging
|
||||
char* debug_event_str = cJSON_Print(event);
|
||||
if (debug_event_str) {
|
||||
printf("Received Auth Event JSON: %s\n", debug_event_str);
|
||||
free(debug_event_str);
|
||||
}
|
||||
log_info("Processing admin auth rule event");
|
||||
|
||||
cJSON* tags_obj = cJSON_GetObjectItem(event, "tags");
|
||||
if (!tags_obj || !cJSON_IsArray(tags_obj)) {
|
||||
log_error("Auth event missing or invalid tags array");
|
||||
snprintf(error_message, error_size, "invalid: auth rule event must have tags");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Tags array size: %d\n", cJSON_GetArraySize(tags_obj));
|
||||
|
||||
// Extract action from content or tags
|
||||
// Parse content for action commands
|
||||
cJSON* content_obj = cJSON_GetObjectItem(event, "content");
|
||||
const char* content = content_obj ? cJSON_GetStringValue(content_obj) : "";
|
||||
printf("Event content: '%s'\n", content);
|
||||
|
||||
// Parse the action from content (should be "add" or "remove")
|
||||
cJSON* content_json = cJSON_Parse(content);
|
||||
char action_buffer[16] = "add"; // Local buffer for action string
|
||||
const char* action = action_buffer; // default
|
||||
char action_buffer[32] = "add"; // default action
|
||||
const char* action = action_buffer;
|
||||
|
||||
if (content_json) {
|
||||
cJSON* action_obj = cJSON_GetObjectItem(content_json, "action");
|
||||
if (action_obj && cJSON_IsString(action_obj)) {
|
||||
@@ -2194,7 +2228,35 @@ int process_admin_auth_event(cJSON* event, char* error_message, size_t error_siz
|
||||
}
|
||||
cJSON_Delete(content_json);
|
||||
}
|
||||
printf("Parsed action: '%s'\n", action);
|
||||
|
||||
printf(" Kind: %d, Action: %s\n", kind, action);
|
||||
|
||||
// Handle query commands
|
||||
if (strcmp(action, "list_all") == 0) {
|
||||
return handle_auth_list_all_query(event, error_message, error_size);
|
||||
}
|
||||
if (strcmp(action, "whitelist_only") == 0) {
|
||||
return handle_auth_whitelist_query(event, error_message, error_size);
|
||||
}
|
||||
if (strcmp(action, "blacklist_only") == 0) {
|
||||
return handle_auth_blacklist_query(event, error_message, error_size);
|
||||
}
|
||||
if (strcmp(action, "pattern_check") == 0) {
|
||||
return handle_auth_pattern_check_query(event, error_message, error_size);
|
||||
}
|
||||
if (strcmp(action, "clear_all_auth_rules") == 0) {
|
||||
return handle_clear_all_auth_rules_command(event, error_message, error_size);
|
||||
}
|
||||
if (strcmp(action, "system_status") == 0) {
|
||||
return handle_system_status_query(event, error_message, error_size);
|
||||
}
|
||||
|
||||
// Handle auth rule updates (add/remove actions)
|
||||
cJSON* tags_obj = cJSON_GetObjectItem(event, "tags");
|
||||
if (!tags_obj || !cJSON_IsArray(tags_obj)) {
|
||||
snprintf(error_message, error_size, "invalid: auth rule event must have tags");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Begin transaction for atomic auth rule updates
|
||||
int rc = sqlite3_exec(g_db, "BEGIN IMMEDIATE TRANSACTION", NULL, NULL, NULL);
|
||||
@@ -2204,33 +2266,11 @@ int process_admin_auth_event(cJSON* event, char* error_message, size_t error_siz
|
||||
}
|
||||
|
||||
int rules_processed = 0;
|
||||
int tags_examined = 0;
|
||||
int tags_skipped = 0;
|
||||
|
||||
// Process each tag as an auth rule specification
|
||||
cJSON* tag = NULL;
|
||||
cJSON_ArrayForEach(tag, tags_obj) {
|
||||
tags_examined++;
|
||||
|
||||
printf("Examining tag #%d:\n", tags_examined);
|
||||
char* tag_debug_str = cJSON_Print(tag);
|
||||
if (tag_debug_str) {
|
||||
printf(" Tag JSON: %s\n", tag_debug_str);
|
||||
free(tag_debug_str);
|
||||
}
|
||||
|
||||
if (!cJSON_IsArray(tag)) {
|
||||
printf(" SKIPPED: Not an array\n");
|
||||
tags_skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
int tag_size = cJSON_GetArraySize(tag);
|
||||
printf(" Tag array size: %d\n", tag_size);
|
||||
|
||||
if (tag_size < 3) {
|
||||
printf(" SKIPPED: Array size < 3 (need at least 3 elements for auth rules)\n");
|
||||
tags_skipped++;
|
||||
if (!cJSON_IsArray(tag) || cJSON_GetArraySize(tag) < 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2241,8 +2281,6 @@ int process_admin_auth_event(cJSON* event, char* error_message, size_t error_siz
|
||||
if (!cJSON_IsString(rule_type_obj) ||
|
||||
!cJSON_IsString(pattern_type_obj) ||
|
||||
!cJSON_IsString(pattern_value_obj)) {
|
||||
printf(" SKIPPED: One or more elements are not strings\n");
|
||||
tags_skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2250,33 +2288,18 @@ int process_admin_auth_event(cJSON* event, char* error_message, size_t error_siz
|
||||
const char* pattern_type = cJSON_GetStringValue(pattern_type_obj);
|
||||
const char* pattern_value = cJSON_GetStringValue(pattern_value_obj);
|
||||
|
||||
printf(" Extracted rule: type='%s', pattern_type='%s', pattern_value='%s'\n",
|
||||
rule_type, pattern_type, pattern_value);
|
||||
|
||||
// Process the auth rule based on action
|
||||
if (strcmp(action, "add") == 0) {
|
||||
printf(" Attempting to add rule to database...\n");
|
||||
if (add_auth_rule_from_config(rule_type, pattern_type, pattern_value, "allow") == 0) {
|
||||
printf(" SUCCESS: Rule added to database\n");
|
||||
rules_processed++;
|
||||
} else {
|
||||
printf(" FAILED: Could not add rule to database\n");
|
||||
}
|
||||
} else if (strcmp(action, "remove") == 0) {
|
||||
printf(" Attempting to remove rule from database...\n");
|
||||
if (remove_auth_rule_from_config(rule_type, pattern_type, pattern_value) == 0) {
|
||||
printf(" SUCCESS: Rule removed from database\n");
|
||||
rules_processed++;
|
||||
} else {
|
||||
printf(" FAILED: Could not remove rule from database\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("Processing summary: examined=%d, skipped=%d, processed=%d\n",
|
||||
tags_examined, tags_skipped, rules_processed);
|
||||
log_info("=== END SERVER-SIDE AUTH RULE EVENT DEBUG ===");
|
||||
|
||||
if (rules_processed > 0) {
|
||||
sqlite3_exec(g_db, "COMMIT", NULL, NULL, NULL);
|
||||
|
||||
@@ -2348,6 +2371,425 @@ int remove_auth_rule_from_config(const char* rule_type, const char* pattern_type
|
||||
return (rc == SQLITE_DONE) ? 0 : -1;
|
||||
}
|
||||
|
||||
// ================================
|
||||
// ADMIN API QUERY HANDLERS
|
||||
// ================================
|
||||
|
||||
// Handle configuration list keys query
|
||||
int handle_config_list_keys_query(cJSON* event, char* error_message, size_t error_size) {
|
||||
(void)event; // Suppress unused parameter warning
|
||||
|
||||
if (!g_db) {
|
||||
snprintf(error_message, error_size, "database not available");
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_info("Processing config list keys query");
|
||||
|
||||
const char* sql = "SELECT key, data_type, category FROM config ORDER BY category, key";
|
||||
sqlite3_stmt* stmt;
|
||||
|
||||
int rc = sqlite3_prepare_v2(g_db, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK) {
|
||||
snprintf(error_message, error_size, "failed to prepare config keys query");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("=== Configuration Keys ===\n");
|
||||
int key_count = 0;
|
||||
|
||||
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
const char* key = (const char*)sqlite3_column_text(stmt, 0);
|
||||
const char* data_type = (const char*)sqlite3_column_text(stmt, 1);
|
||||
const char* category = (const char*)sqlite3_column_text(stmt, 2);
|
||||
|
||||
printf(" [%s] %s (%s)\n", category ? category : "general", key ? key : "", data_type ? data_type : "string");
|
||||
key_count++;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
printf("Total configuration keys: %d\n", key_count);
|
||||
log_success("Configuration keys listed successfully");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle get current configuration query
|
||||
int handle_config_get_current_query(cJSON* event, char* error_message, size_t error_size) {
|
||||
(void)event; // Suppress unused parameter warning
|
||||
|
||||
if (!g_db) {
|
||||
snprintf(error_message, error_size, "database not available");
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_info("Processing get current config query");
|
||||
|
||||
const char* sql = "SELECT key, value, data_type, category FROM config ORDER BY category, key";
|
||||
sqlite3_stmt* stmt;
|
||||
|
||||
int rc = sqlite3_prepare_v2(g_db, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK) {
|
||||
snprintf(error_message, error_size, "failed to prepare current config query");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("=== Current Configuration ===\n");
|
||||
int config_count = 0;
|
||||
|
||||
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
const char* key = (const char*)sqlite3_column_text(stmt, 0);
|
||||
const char* value = (const char*)sqlite3_column_text(stmt, 1);
|
||||
const char* data_type = (const char*)sqlite3_column_text(stmt, 2);
|
||||
const char* category = (const char*)sqlite3_column_text(stmt, 3);
|
||||
|
||||
printf(" [%s] %s = %s (%s)\n",
|
||||
category ? category : "general",
|
||||
key ? key : "",
|
||||
value ? value : "",
|
||||
data_type ? data_type : "string");
|
||||
config_count++;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
printf("Total configuration items: %d\n", config_count);
|
||||
log_success("Current configuration retrieved successfully");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle auth rules list all query
|
||||
int handle_auth_list_all_query(cJSON* event, char* error_message, size_t error_size) {
|
||||
(void)event; // Suppress unused parameter warning
|
||||
|
||||
if (!g_db) {
|
||||
snprintf(error_message, error_size, "database not available");
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_info("Processing auth rules list all query");
|
||||
|
||||
const char* sql = "SELECT rule_type, pattern_type, pattern_value, action FROM auth_rules ORDER BY rule_type, pattern_type";
|
||||
sqlite3_stmt* stmt;
|
||||
|
||||
int rc = sqlite3_prepare_v2(g_db, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK) {
|
||||
snprintf(error_message, error_size, "failed to prepare auth rules query");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("=== All Auth Rules ===\n");
|
||||
int rule_count = 0;
|
||||
|
||||
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
const char* rule_type = (const char*)sqlite3_column_text(stmt, 0);
|
||||
const char* pattern_type = (const char*)sqlite3_column_text(stmt, 1);
|
||||
const char* pattern_value = (const char*)sqlite3_column_text(stmt, 2);
|
||||
const char* action = (const char*)sqlite3_column_text(stmt, 3);
|
||||
|
||||
printf(" %s %s:%s -> %s\n",
|
||||
rule_type ? rule_type : "",
|
||||
pattern_type ? pattern_type : "",
|
||||
pattern_value ? pattern_value : "",
|
||||
action ? action : "allow");
|
||||
rule_count++;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
printf("Total auth rules: %d\n", rule_count);
|
||||
log_success("Auth rules listed successfully");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle whitelist only query
|
||||
int handle_auth_whitelist_query(cJSON* event, char* error_message, size_t error_size) {
|
||||
(void)event; // Suppress unused parameter warning
|
||||
|
||||
if (!g_db) {
|
||||
snprintf(error_message, error_size, "database not available");
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_info("Processing whitelist rules query");
|
||||
|
||||
const char* sql = "SELECT rule_type, pattern_type, pattern_value, action FROM auth_rules WHERE rule_type LIKE '%whitelist%' ORDER BY pattern_type";
|
||||
sqlite3_stmt* stmt;
|
||||
|
||||
int rc = sqlite3_prepare_v2(g_db, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK) {
|
||||
snprintf(error_message, error_size, "failed to prepare whitelist query");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("=== Whitelist Rules ===\n");
|
||||
int whitelist_count = 0;
|
||||
|
||||
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
const char* rule_type = (const char*)sqlite3_column_text(stmt, 0);
|
||||
const char* pattern_type = (const char*)sqlite3_column_text(stmt, 1);
|
||||
const char* pattern_value = (const char*)sqlite3_column_text(stmt, 2);
|
||||
const char* action = (const char*)sqlite3_column_text(stmt, 3);
|
||||
|
||||
printf(" %s %s:%s -> %s\n",
|
||||
rule_type ? rule_type : "",
|
||||
pattern_type ? pattern_type : "",
|
||||
pattern_value ? pattern_value : "",
|
||||
action ? action : "allow");
|
||||
whitelist_count++;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
printf("Total whitelist rules: %d\n", whitelist_count);
|
||||
log_success("Whitelist rules listed successfully");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle blacklist only query
|
||||
int handle_auth_blacklist_query(cJSON* event, char* error_message, size_t error_size) {
|
||||
(void)event; // Suppress unused parameter warning
|
||||
|
||||
if (!g_db) {
|
||||
snprintf(error_message, error_size, "database not available");
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_info("Processing blacklist rules query");
|
||||
|
||||
const char* sql = "SELECT rule_type, pattern_type, pattern_value, action FROM auth_rules WHERE rule_type LIKE '%blacklist%' ORDER BY pattern_type";
|
||||
sqlite3_stmt* stmt;
|
||||
|
||||
int rc = sqlite3_prepare_v2(g_db, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK) {
|
||||
snprintf(error_message, error_size, "failed to prepare blacklist query");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("=== Blacklist Rules ===\n");
|
||||
int blacklist_count = 0;
|
||||
|
||||
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
const char* rule_type = (const char*)sqlite3_column_text(stmt, 0);
|
||||
const char* pattern_type = (const char*)sqlite3_column_text(stmt, 1);
|
||||
const char* pattern_value = (const char*)sqlite3_column_text(stmt, 2);
|
||||
const char* action = (const char*)sqlite3_column_text(stmt, 3);
|
||||
|
||||
printf(" %s %s:%s -> %s\n",
|
||||
rule_type ? rule_type : "",
|
||||
pattern_type ? pattern_type : "",
|
||||
pattern_value ? pattern_value : "",
|
||||
action ? action : "deny");
|
||||
blacklist_count++;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
printf("Total blacklist rules: %d\n", blacklist_count);
|
||||
log_success("Blacklist rules listed successfully");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle pattern check query
|
||||
int handle_auth_pattern_check_query(cJSON* event, char* error_message, size_t error_size) {
|
||||
// Parse tags to get the pattern to check
|
||||
cJSON* tags_obj = cJSON_GetObjectItem(event, "tags");
|
||||
if (!tags_obj || !cJSON_IsArray(tags_obj)) {
|
||||
snprintf(error_message, error_size, "invalid: pattern check requires tags with pattern information");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char* check_pattern_type = NULL;
|
||||
const char* check_pattern_value = NULL;
|
||||
|
||||
// Find pattern_check tag
|
||||
cJSON* tag = NULL;
|
||||
cJSON_ArrayForEach(tag, tags_obj) {
|
||||
if (cJSON_IsArray(tag) && cJSON_GetArraySize(tag) >= 3) {
|
||||
cJSON* tag_name = cJSON_GetArrayItem(tag, 0);
|
||||
if (tag_name && cJSON_IsString(tag_name) &&
|
||||
strcmp(cJSON_GetStringValue(tag_name), "pattern_check") == 0) {
|
||||
|
||||
cJSON* pattern_type_obj = cJSON_GetArrayItem(tag, 1);
|
||||
cJSON* pattern_value_obj = cJSON_GetArrayItem(tag, 2);
|
||||
|
||||
if (pattern_type_obj && cJSON_IsString(pattern_type_obj) &&
|
||||
pattern_value_obj && cJSON_IsString(pattern_value_obj)) {
|
||||
check_pattern_type = cJSON_GetStringValue(pattern_type_obj);
|
||||
check_pattern_value = cJSON_GetStringValue(pattern_value_obj);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!check_pattern_type || !check_pattern_value) {
|
||||
snprintf(error_message, error_size, "invalid: pattern_check tag format should be [\"pattern_check\", \"pattern_type\", \"pattern_value\"]");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!g_db) {
|
||||
snprintf(error_message, error_size, "database not available");
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_info("Processing pattern check query");
|
||||
printf(" Checking pattern: %s:%s\n", check_pattern_type, check_pattern_value);
|
||||
|
||||
const char* sql = "SELECT rule_type, pattern_type, pattern_value, action FROM auth_rules WHERE pattern_type = ? AND pattern_value = ? ORDER BY rule_type";
|
||||
sqlite3_stmt* stmt;
|
||||
|
||||
int rc = sqlite3_prepare_v2(g_db, sql, -1, &stmt, NULL);
|
||||
if (rc != SQLITE_OK) {
|
||||
snprintf(error_message, error_size, "failed to prepare pattern check query");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sqlite3_bind_text(stmt, 1, check_pattern_type, -1, SQLITE_STATIC);
|
||||
sqlite3_bind_text(stmt, 2, check_pattern_value, -1, SQLITE_STATIC);
|
||||
|
||||
printf("=== Pattern Check Results ===\n");
|
||||
printf("Pattern: %s:%s\n", check_pattern_type, check_pattern_value);
|
||||
int match_count = 0;
|
||||
|
||||
while (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
const char* rule_type = (const char*)sqlite3_column_text(stmt, 0);
|
||||
const char* pattern_type = (const char*)sqlite3_column_text(stmt, 1);
|
||||
const char* pattern_value = (const char*)sqlite3_column_text(stmt, 2);
|
||||
const char* action = (const char*)sqlite3_column_text(stmt, 3);
|
||||
|
||||
printf(" MATCH: %s %s:%s -> %s\n",
|
||||
rule_type ? rule_type : "",
|
||||
pattern_type ? pattern_type : "",
|
||||
pattern_value ? pattern_value : "",
|
||||
action ? action : "allow");
|
||||
match_count++;
|
||||
}
|
||||
|
||||
sqlite3_finalize(stmt);
|
||||
|
||||
if (match_count == 0) {
|
||||
printf(" No matching rules found for this pattern\n");
|
||||
}
|
||||
|
||||
printf("Total matches: %d\n", match_count);
|
||||
log_success("Pattern check completed successfully");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle clear all auth rules command
|
||||
int handle_clear_all_auth_rules_command(cJSON* event, char* error_message, size_t error_size) {
|
||||
(void)event; // Suppress unused parameter warning
|
||||
|
||||
if (!g_db) {
|
||||
snprintf(error_message, error_size, "database not available");
|
||||
return -1;
|
||||
}
|
||||
|
||||
log_info("Processing clear all auth rules command");
|
||||
|
||||
// Count existing rules first
|
||||
const char* count_sql = "SELECT COUNT(*) FROM auth_rules";
|
||||
sqlite3_stmt* count_stmt;
|
||||
|
||||
int rc = sqlite3_prepare_v2(g_db, count_sql, -1, &count_stmt, NULL);
|
||||
if (rc != SQLITE_OK) {
|
||||
snprintf(error_message, error_size, "failed to prepare count query");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int rule_count = 0;
|
||||
if (sqlite3_step(count_stmt) == SQLITE_ROW) {
|
||||
rule_count = sqlite3_column_int(count_stmt, 0);
|
||||
}
|
||||
sqlite3_finalize(count_stmt);
|
||||
|
||||
// Delete all auth rules (this operation succeeds even if table is empty)
|
||||
const char* delete_sql = "DELETE FROM auth_rules";
|
||||
rc = sqlite3_exec(g_db, delete_sql, NULL, NULL, NULL);
|
||||
|
||||
if (rc != SQLITE_OK) {
|
||||
snprintf(error_message, error_size, "failed to execute clear auth rules command");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Always return success - clearing empty table is still a successful operation
|
||||
if (rule_count > 0) {
|
||||
printf("Cleared %d auth rules from database\n", rule_count);
|
||||
log_success("All auth rules cleared successfully");
|
||||
} else {
|
||||
printf("Auth rules table was already empty - no rules to clear\n");
|
||||
log_success("Clear auth rules completed successfully (table was already empty)");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Handle system status query
|
||||
int handle_system_status_query(cJSON* event, char* error_message, size_t error_size) {
|
||||
(void)event; // Suppress unused parameter warning
|
||||
(void)error_message; // This command always succeeds
|
||||
(void)error_size;
|
||||
|
||||
log_info("Processing system status query");
|
||||
|
||||
printf("=== System Status ===\n");
|
||||
|
||||
// Database status
|
||||
printf("Database: %s\n", g_db ? "Connected" : "Not available");
|
||||
if (strlen(g_database_path) > 0) {
|
||||
printf("Database path: %s\n", g_database_path);
|
||||
}
|
||||
|
||||
// Configuration status
|
||||
printf("Unified cache: %s\n", g_unified_cache.cache_valid ? "Valid" : "Invalid");
|
||||
printf("Admin pubkey: %s\n", g_unified_cache.admin_pubkey[0] ? g_unified_cache.admin_pubkey : "Not set");
|
||||
printf("Relay pubkey: %s\n", g_unified_cache.relay_pubkey[0] ? g_unified_cache.relay_pubkey : "Not set");
|
||||
|
||||
// Count configuration items
|
||||
if (g_db) {
|
||||
const char* config_count_sql = "SELECT COUNT(*) FROM config";
|
||||
sqlite3_stmt* stmt;
|
||||
|
||||
if (sqlite3_prepare_v2(g_db, config_count_sql, -1, &stmt, NULL) == SQLITE_OK) {
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
int config_count = sqlite3_column_int(stmt, 0);
|
||||
printf("Configuration items: %d\n", config_count);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
|
||||
// Count auth rules
|
||||
const char* auth_count_sql = "SELECT COUNT(*) FROM auth_rules";
|
||||
if (sqlite3_prepare_v2(g_db, auth_count_sql, -1, &stmt, NULL) == SQLITE_OK) {
|
||||
if (sqlite3_step(stmt) == SQLITE_ROW) {
|
||||
int auth_count = sqlite3_column_int(stmt, 0);
|
||||
printf("Auth rules: %d\n", auth_count);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
// Cache expiration
|
||||
if (g_unified_cache.cache_expires > 0) {
|
||||
time_t now = time(NULL);
|
||||
long seconds_to_expire = g_unified_cache.cache_expires - now;
|
||||
printf("Cache expires in: %ld seconds\n", seconds_to_expire);
|
||||
}
|
||||
|
||||
printf("System time: %ld\n", (long)time(NULL));
|
||||
|
||||
log_success("System status retrieved successfully");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ================================
|
||||
// CONFIGURATION CACHE MANAGEMENT
|
||||
// ================================
|
||||
|
||||
Reference in New Issue
Block a user