Add node name lookup by public key and enhance CORS handling in API endpoints

This commit is contained in:
Lloyd
2025-12-18 21:26:31 +00:00
parent 3f57e78d6a
commit d321612670
3 changed files with 97 additions and 4 deletions
@@ -186,6 +186,27 @@ class StorageCollector:
def get_neighbors(self) -> dict:
return self.sqlite_handler.get_neighbors()
def get_node_name_by_pubkey(self, pubkey: str) -> Optional[str]:
"""
Lookup node name from adverts table by public key.
Args:
pubkey: Public key in hex string format
Returns:
Node name if found, None otherwise
"""
try:
with self.sqlite_handler.get_connection() as conn:
result = conn.execute(
"SELECT node_name FROM adverts WHERE pubkey = ? AND node_name IS NOT NULL ORDER BY last_seen DESC LIMIT 1",
(pubkey,)
).fetchone()
return result[0] if result else None
except Exception as e:
logger.debug(f"Could not lookup node name for {pubkey[:8] if pubkey else 'None'}: {e}")
return None
def cleanup_old_data(self, days: int = 7):
self.sqlite_handler.cleanup_old_data(days)
+31 -3
View File
@@ -207,12 +207,24 @@ class RoomServer:
f"{client_pubkey[:4].hex()}: {message_text[:50]}"
)
# Update client activity timestamp (they're clearly active if posting)
# This prevents them from being evicted while they're actively posting
# Log authenticated clients count for debugging distribution
all_clients = self.acl.get_all_clients()
logger.info(
f"Room '{self.room_name}': Message stored, will distribute to "
f"{len(all_clients)} authenticated client(s)"
)
# Update client's sync_since to this message's timestamp
# This prevents the author from receiving their own message back
# Also update activity timestamp (they're clearly active if posting)
logger.debug(
f"Room '{self.room_name}': Updating author's sync_since to {post_timestamp} "
f"to prevent echo"
)
self.db.upsert_client_sync(
room_hash=f"0x{self.room_hash:02X}",
client_pubkey=client_pubkey.hex(),
sync_since=0, # Will be preserved if already set
sync_since=post_timestamp, # Don't send this message back to author
last_activity=time.time()
)
@@ -488,9 +500,15 @@ class RoomServer:
# Get all clients for this room
all_clients = self.acl.get_all_clients()
if not all_clients:
logger.debug(f"Room '{self.room_name}': No authenticated clients found")
self.next_push_time = time.time() + 1.0 # Check again in 1 second
continue
logger.debug(
f"Room '{self.room_name}': Found {len(all_clients)} authenticated client(s), "
f"checking for unsynced messages"
)
# SAFETY: Limit number of clients
if len(all_clients) > MAX_CLIENTS_PER_ROOM:
logger.warning(
@@ -555,6 +573,12 @@ class RoomServer:
last_activity=time.time()
)
# Log the sync check for debugging
logger.debug(
f"Room '{self.room_name}': Checking client 0x{client.id.get_public_key()[0]:02X} "
f"for messages newer than sync_since={sync_since:.1f}"
)
# Find next unsynced message for this client
unsynced = self.db.get_unsynced_messages(
room_hash=f"0x{self.room_hash:02X}",
@@ -565,6 +589,10 @@ class RoomServer:
if unsynced:
post = unsynced[0]
logger.debug(
f"Room '{self.room_name}': Client 0x{client.id.get_public_key()[0]:02X} "
f"has unsynced message #{post['id']}, post_timestamp={post['post_timestamp']:.1f}"
)
# Check if enough time has passed since post creation
now = time.time()
if now >= post['post_timestamp'] + POST_SYNC_DELAY_SECS:
+45 -1
View File
@@ -2069,6 +2069,12 @@ class APIEndpoints:
}
}
"""
# Enable CORS for this endpoint only if configured
self._set_cors_headers()
if cherrypy.request.method == "OPTIONS":
return ""
try:
room_info = self._get_room_server_by_name_or_hash(room_name, room_hash)
room_server = room_info['room_server']
@@ -2094,7 +2100,8 @@ class APIEndpoints:
offset=int(offset)
)
# Format messages with author prefix
# Format messages with author prefix and lookup sender names
storage = self._get_storage()
formatted_messages = []
for msg in messages:
author_pubkey = msg['author_pubkey']
@@ -2108,6 +2115,13 @@ class APIEndpoints:
'txt_type': msg['txt_type'],
'created_at': msg.get('created_at', msg['post_timestamp'])
}
# Lookup sender name from adverts table
if author_pubkey:
author_name = storage.get_node_name_by_pubkey(author_pubkey)
if author_name:
formatted_msg['author_name'] = author_name
formatted_messages.append(formatted_msg)
return self._success({
@@ -2146,6 +2160,12 @@ class APIEndpoints:
Returns:
{"success": true, "data": {"message_id": 123}}
"""
# Enable CORS for this endpoint only if configured
self._set_cors_headers()
if cherrypy.request.method == "OPTIONS":
return ""
try:
self._require_post()
@@ -2268,6 +2288,12 @@ class APIEndpoints:
}
}
"""
# Enable CORS for this endpoint only if configured
self._set_cors_headers()
if cherrypy.request.method == "OPTIONS":
return ""
try:
if not self.daemon_instance or not hasattr(self.daemon_instance, 'text_helper'):
return self._error("Text helper not available")
@@ -2399,6 +2425,12 @@ class APIEndpoints:
}
}
"""
# Enable CORS for this endpoint only if configured
self._set_cors_headers()
if cherrypy.request.method == "OPTIONS":
return ""
try:
# Reuse room_stats logic but return only clients
stats = self.room_stats(room_name=room_name, room_hash=room_hash)
@@ -2431,6 +2463,12 @@ class APIEndpoints:
Returns:
{"success": true}
"""
# Enable CORS for this endpoint only if configured
self._set_cors_headers()
if cherrypy.request.method == "OPTIONS":
return ""
try:
if cherrypy.request.method != "DELETE":
cherrypy.response.status = 405
@@ -2473,6 +2511,12 @@ class APIEndpoints:
Returns:
{"success": true, "data": {"deleted_count": 123}}
"""
# Enable CORS for this endpoint only if configured
self._set_cors_headers()
if cherrypy.request.method == "OPTIONS":
return ""
try:
if cherrypy.request.method != "DELETE":
cherrypy.response.status = 405