Enhance room access validation and debugging in command handling
Improved error handling in `handle_init_command` and `handle_join_command` to provide clearer feedback when room resolution fails. Added detailed debug logging for room access attempts, including client ID and requested room information, when debugging is enabled. Introduced a new function, `room_debug_enabled`, to toggle debug logging based on environment variables. Updated password validation logic to require a password when one is set for a room.
This commit is contained in:
@@ -2,6 +2,7 @@ use crate::types::{ChatState, ClientId, Command, RoomMeta, ServerConfig};
|
||||
use bcrypt::verify as bcrypt_verify;
|
||||
use serde_json::{json, Value};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::env;
|
||||
use std::sync::Arc;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use tokio::sync::RwLock;
|
||||
@@ -160,11 +161,22 @@ async fn handle_init_command(
|
||||
let (resolved_room_name, room_meta) = {
|
||||
let guard = state.read().await;
|
||||
let Some(resolved_room_name) = resolve_room_name(&guard, &room_name) else {
|
||||
send_error(client_id, Arc::clone(&state), "room_not_found_or_join_failed").await;
|
||||
if room_debug_enabled() {
|
||||
let known_rooms = guard.room_meta.keys().cloned().collect::<Vec<_>>();
|
||||
eprintln!(
|
||||
"[yourchat2][room-debug][init] client_id={client_id} requested_room='{room_name}' resolve_failed known_rooms={known_rooms:?}"
|
||||
);
|
||||
}
|
||||
send_error(client_id, Arc::clone(&state), "room_not_found").await;
|
||||
return;
|
||||
};
|
||||
let Some(room_meta) = guard.room_meta.get(&resolved_room_name).cloned() else {
|
||||
send_error(client_id, Arc::clone(&state), "room_not_found_or_join_failed").await;
|
||||
if room_debug_enabled() {
|
||||
eprintln!(
|
||||
"[yourchat2][room-debug][init] client_id={client_id} requested_room='{room_name}' resolved_room='{resolved_room_name}' missing_meta"
|
||||
);
|
||||
}
|
||||
send_error(client_id, Arc::clone(&state), "room_not_found").await;
|
||||
return;
|
||||
};
|
||||
(resolved_room_name, room_meta)
|
||||
@@ -181,6 +193,20 @@ async fn handle_init_command(
|
||||
)
|
||||
.await
|
||||
{
|
||||
if room_debug_enabled() {
|
||||
eprintln!(
|
||||
"[yourchat2][room-debug][init] client_id={client_id} user='{}' room='{}' denied='{}' user_profile={{fid:{:?},gender:{:?},age:{:?},rights:{:?},right_ids:{:?}}} room_meta={:?}",
|
||||
profile.display_name,
|
||||
resolved_room_name,
|
||||
access_error,
|
||||
profile.falukant_user_id,
|
||||
profile.gender_id,
|
||||
profile.age,
|
||||
profile.rights,
|
||||
profile.right_type_ids,
|
||||
room_meta
|
||||
);
|
||||
}
|
||||
send_error(client_id, Arc::clone(&state), access_error).await;
|
||||
return;
|
||||
}
|
||||
@@ -199,7 +225,12 @@ async fn handle_init_command(
|
||||
}
|
||||
if !guard.room_meta.contains_key(&resolved_room_name) {
|
||||
drop(guard);
|
||||
send_error(client_id, Arc::clone(&state), "room_not_found_or_join_failed").await;
|
||||
if room_debug_enabled() {
|
||||
eprintln!(
|
||||
"[yourchat2][room-debug][init] client_id={client_id} resolved_room='{resolved_room_name}' vanished_before_join"
|
||||
);
|
||||
}
|
||||
send_error(client_id, Arc::clone(&state), "room_not_found").await;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -299,11 +330,22 @@ async fn handle_join_command(
|
||||
let (resolved_room, room_meta, falukant_user_id, gender_id, age, right_type_ids, rights) = {
|
||||
let guard = state.read().await;
|
||||
let Some(resolved_room) = resolve_room_name(&guard, &room) else {
|
||||
send_error(client_id, Arc::clone(&state), "room_not_found_or_join_failed").await;
|
||||
if room_debug_enabled() {
|
||||
let known_rooms = guard.room_meta.keys().cloned().collect::<Vec<_>>();
|
||||
eprintln!(
|
||||
"[yourchat2][room-debug][join] client_id={client_id} requested_room='{room}' resolve_failed known_rooms={known_rooms:?}"
|
||||
);
|
||||
}
|
||||
send_error(client_id, Arc::clone(&state), "room_not_found").await;
|
||||
return;
|
||||
};
|
||||
let Some(room_meta) = guard.room_meta.get(&resolved_room).cloned() else {
|
||||
send_error(client_id, Arc::clone(&state), "room_not_found_or_join_failed").await;
|
||||
if room_debug_enabled() {
|
||||
eprintln!(
|
||||
"[yourchat2][room-debug][join] client_id={client_id} requested_room='{room}' resolved_room='{resolved_room}' missing_meta"
|
||||
);
|
||||
}
|
||||
send_error(client_id, Arc::clone(&state), "room_not_found").await;
|
||||
return;
|
||||
};
|
||||
let Some(client) = guard.clients.get(&client_id) else {
|
||||
@@ -331,6 +373,19 @@ async fn handle_join_command(
|
||||
)
|
||||
.await
|
||||
{
|
||||
if room_debug_enabled() {
|
||||
eprintln!(
|
||||
"[yourchat2][room-debug][join] client_id={client_id} room='{}' denied='{}' user={{fid:{:?},gender:{:?},age:{:?},rights:{:?},right_ids:{:?}}} room_meta={:?}",
|
||||
resolved_room,
|
||||
access_error,
|
||||
falukant_user_id,
|
||||
gender_id,
|
||||
age,
|
||||
rights,
|
||||
right_type_ids,
|
||||
room_meta
|
||||
);
|
||||
}
|
||||
send_error(client_id, Arc::clone(&state), access_error).await;
|
||||
return;
|
||||
}
|
||||
@@ -338,7 +393,12 @@ async fn handle_join_command(
|
||||
let mut guard = state.write().await;
|
||||
if !guard.room_meta.contains_key(&resolved_room) {
|
||||
drop(guard);
|
||||
send_error(client_id, Arc::clone(&state), "room_not_found_or_join_failed").await;
|
||||
if room_debug_enabled() {
|
||||
eprintln!(
|
||||
"[yourchat2][room-debug][join] client_id={client_id} resolved_room='{resolved_room}' vanished_before_join"
|
||||
);
|
||||
}
|
||||
send_error(client_id, Arc::clone(&state), "room_not_found").await;
|
||||
return;
|
||||
}
|
||||
let Some(client) = guard.clients.get_mut(&client_id) else {
|
||||
@@ -883,6 +943,12 @@ async fn handle_create_room_command(
|
||||
empty_since_unix: Some(now_unix()),
|
||||
},
|
||||
);
|
||||
if room_debug_enabled() {
|
||||
eprintln!(
|
||||
"[yourchat2][room-debug][create] client_id={client_id} room='{}' owner_chat_user_id={} created",
|
||||
parsed.room_name, owner_chat_user_id
|
||||
);
|
||||
}
|
||||
}
|
||||
state::send_room_list(client_id, Arc::clone(&state)).await;
|
||||
state::send_to_client(
|
||||
@@ -1133,8 +1199,13 @@ async fn room_access_allowed(
|
||||
}
|
||||
|
||||
if let Some(room_password) = &room.password {
|
||||
if !room_password.is_empty() && !password_matches(room_password, provided_password) {
|
||||
return Err("room_password_invalid");
|
||||
if !room_password.is_empty() {
|
||||
if provided_password.trim().is_empty() {
|
||||
return Err("room_password_required");
|
||||
}
|
||||
if !password_matches(room_password, provided_password) {
|
||||
return Err("room_password_invalid");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1361,6 +1432,13 @@ fn now_unix() -> i64 {
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
fn room_debug_enabled() -> bool {
|
||||
matches!(
|
||||
env::var("CHAT_DEBUG_ROOM_ACCESS").ok().as_deref(),
|
||||
Some("1") | Some("true") | Some("TRUE") | Some("yes") | Some("YES") | Some("on") | Some("ON")
|
||||
)
|
||||
}
|
||||
|
||||
fn command_from_chat_line(message: &str, token: Option<String>) -> Option<Command> {
|
||||
let trimmed = message.trim();
|
||||
if !trimmed.starts_with('/') {
|
||||
|
||||
Reference in New Issue
Block a user