style(server,agent): fmt + clippy fixes for Task 5 (CI green)
All checks were successful
All checks were successful
9082e11 compiles + passes all 50 server tests on the build host; only blocked
CI on cargo fmt (4 files) and one clippy -D dead-code denial:
- cargo fmt --all (relay/mod.rs, session/mod.rs, agent consent/mod.rs + session/mod.rs)
- #[cfg_attr(not(test), allow(dead_code))] on session::get_consent_state (a
read accessor currently exercised only by tests)
No logic change.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -73,8 +73,7 @@ pub fn prompt_consent(technician_name: &str, access: ConsentAccessMode) -> bool
|
|||||||
use std::os::windows::ffi::OsStrExt;
|
use std::os::windows::ffi::OsStrExt;
|
||||||
use windows::core::PCWSTR;
|
use windows::core::PCWSTR;
|
||||||
use windows::Win32::UI::WindowsAndMessaging::{
|
use windows::Win32::UI::WindowsAndMessaging::{
|
||||||
MessageBoxW, IDYES, MB_ICONQUESTION, MB_SETFOREGROUND, MB_SYSTEMMODAL, MB_TOPMOST,
|
MessageBoxW, IDYES, MB_ICONQUESTION, MB_SETFOREGROUND, MB_SYSTEMMODAL, MB_TOPMOST, MB_YESNO,
|
||||||
MB_YESNO,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let title = "GuruConnect - Remote Support Request";
|
let title = "GuruConnect - Remote Support Request";
|
||||||
@@ -150,6 +149,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn access_mode_from_proto_defaults_to_control() {
|
fn access_mode_from_proto_defaults_to_control() {
|
||||||
// An out-of-range proto value must not under-state access.
|
// An out-of-range proto value must not under-state access.
|
||||||
assert_eq!(ConsentAccessMode::from_proto(999), ConsentAccessMode::Control);
|
assert_eq!(
|
||||||
|
ConsentAccessMode::from_proto(999),
|
||||||
|
ConsentAccessMode::Control
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -533,15 +533,13 @@ impl SessionManager {
|
|||||||
|
|
||||||
// The MessageBox blocks the calling thread; run it on the blocking pool
|
// The MessageBox blocks the calling thread; run it on the blocking pool
|
||||||
// so the agent's async loop is not stalled and heartbeats keep flowing.
|
// so the agent's async loop is not stalled and heartbeats keep flowing.
|
||||||
let granted = tokio::task::spawn_blocking(move || {
|
let granted = tokio::task::spawn_blocking(move || prompt_consent(&technician_name, access))
|
||||||
prompt_consent(&technician_name, access)
|
.await
|
||||||
})
|
.unwrap_or_else(|e| {
|
||||||
.await
|
// The blocking task panicked — fail closed (deny).
|
||||||
.unwrap_or_else(|e| {
|
tracing::error!("Consent dialog task failed: {}; denying", e);
|
||||||
// The blocking task panicked — fail closed (deny).
|
false
|
||||||
tracing::error!("Consent dialog task failed: {}; denying", e);
|
});
|
||||||
false
|
|
||||||
});
|
|
||||||
|
|
||||||
tracing::info!(
|
tracing::info!(
|
||||||
"End user {} consent for session {}",
|
"End user {} consent for session {}",
|
||||||
|
|||||||
@@ -851,7 +851,8 @@ async fn handle_agent_connection(
|
|||||||
tracing::debug!(
|
tracing::debug!(
|
||||||
"Late ConsentResponse from agent {} on session {}; ignoring \
|
"Late ConsentResponse from agent {} on session {}; ignoring \
|
||||||
(consent already finalized)",
|
(consent already finalized)",
|
||||||
agent_id, session_id
|
agent_id,
|
||||||
|
session_id
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
@@ -978,7 +979,16 @@ async fn run_consent_handshake(
|
|||||||
"Failed to encode ConsentRequest for session {}; denying",
|
"Failed to encode ConsentRequest for session {}; denying",
|
||||||
session_id
|
session_id
|
||||||
);
|
);
|
||||||
finalize_consent(sessions, db, session_id, agent_id, false, "encode_error", client_ip).await;
|
finalize_consent(
|
||||||
|
sessions,
|
||||||
|
db,
|
||||||
|
session_id,
|
||||||
|
agent_id,
|
||||||
|
false,
|
||||||
|
"encode_error",
|
||||||
|
client_ip,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ws_sender.send(Message::Binary(buf)).await.is_err() {
|
if ws_sender.send(Message::Binary(buf)).await.is_err() {
|
||||||
@@ -986,7 +996,16 @@ async fn run_consent_handshake(
|
|||||||
"Failed to send ConsentRequest to agent {} (session {}); denying",
|
"Failed to send ConsentRequest to agent {} (session {}); denying",
|
||||||
agent_id, session_id
|
agent_id, session_id
|
||||||
);
|
);
|
||||||
finalize_consent(sessions, db, session_id, agent_id, false, "send_error", client_ip).await;
|
finalize_consent(
|
||||||
|
sessions,
|
||||||
|
db,
|
||||||
|
session_id,
|
||||||
|
agent_id,
|
||||||
|
false,
|
||||||
|
"send_error",
|
||||||
|
client_ip,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1010,8 +1029,8 @@ async fn run_consent_handshake(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Wait for the ConsentResponse, bounded by the timeout.
|
// 2. Wait for the ConsentResponse, bounded by the timeout.
|
||||||
let deadline = tokio::time::Instant::now()
|
let deadline =
|
||||||
+ std::time::Duration::from_secs(CONSENT_TIMEOUT_SECS);
|
tokio::time::Instant::now() + std::time::Duration::from_secs(CONSENT_TIMEOUT_SECS);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let remaining = deadline.saturating_duration_since(tokio::time::Instant::now());
|
let remaining = deadline.saturating_duration_since(tokio::time::Instant::now());
|
||||||
@@ -1020,7 +1039,10 @@ async fn run_consent_handshake(
|
|||||||
"Attended session {}: consent timed out after {}s; denying",
|
"Attended session {}: consent timed out after {}s; denying",
|
||||||
session_id, CONSENT_TIMEOUT_SECS
|
session_id, CONSENT_TIMEOUT_SECS
|
||||||
);
|
);
|
||||||
finalize_consent(sessions, db, session_id, agent_id, false, "timeout", client_ip).await;
|
finalize_consent(
|
||||||
|
sessions, db, session_id, agent_id, false, "timeout", client_ip,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1031,8 +1053,10 @@ async fn run_consent_handshake(
|
|||||||
"Attended session {}: consent timed out after {}s; denying",
|
"Attended session {}: consent timed out after {}s; denying",
|
||||||
session_id, CONSENT_TIMEOUT_SECS
|
session_id, CONSENT_TIMEOUT_SECS
|
||||||
);
|
);
|
||||||
finalize_consent(sessions, db, session_id, agent_id, false, "timeout", client_ip)
|
finalize_consent(
|
||||||
.await;
|
sessions, db, session_id, agent_id, false, "timeout", client_ip,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Socket closed before answering.
|
// Socket closed before answering.
|
||||||
@@ -1042,7 +1066,13 @@ async fn run_consent_handshake(
|
|||||||
session_id, agent_id
|
session_id, agent_id
|
||||||
);
|
);
|
||||||
finalize_consent(
|
finalize_consent(
|
||||||
sessions, db, session_id, agent_id, false, "agent_disconnected", client_ip,
|
sessions,
|
||||||
|
db,
|
||||||
|
session_id,
|
||||||
|
agent_id,
|
||||||
|
false,
|
||||||
|
"agent_disconnected",
|
||||||
|
client_ip,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
return false;
|
return false;
|
||||||
@@ -1106,7 +1136,13 @@ async fn run_consent_handshake(
|
|||||||
session_id, agent_id
|
session_id, agent_id
|
||||||
);
|
);
|
||||||
finalize_consent(
|
finalize_consent(
|
||||||
sessions, db, session_id, agent_id, false, "agent_closed", client_ip,
|
sessions,
|
||||||
|
db,
|
||||||
|
session_id,
|
||||||
|
agent_id,
|
||||||
|
false,
|
||||||
|
"agent_closed",
|
||||||
|
client_ip,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
return false;
|
return false;
|
||||||
@@ -1152,8 +1188,8 @@ async fn finalize_consent(
|
|||||||
|
|
||||||
if let Some(db) = db {
|
if let Some(db) = db {
|
||||||
// Durable mirror of the consent decision on the session row.
|
// Durable mirror of the consent decision on the session row.
|
||||||
let _ = db::sessions::update_consent_state(db.pool(), session_id, new_state.as_db_str())
|
let _ =
|
||||||
.await;
|
db::sessions::update_consent_state(db.pool(), session_id, new_state.as_db_str()).await;
|
||||||
|
|
||||||
// Audit event (consent_granted | consent_denied) with the agent id and
|
// Audit event (consent_granted | consent_denied) with the agent id and
|
||||||
// the (non-secret) reason so the decision is fully traceable.
|
// the (non-secret) reason so the decision is fully traceable.
|
||||||
|
|||||||
@@ -294,6 +294,9 @@ impl SessionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the current attended-consent state for a session, if it exists.
|
/// Get the current attended-consent state for a session, if it exists.
|
||||||
|
/// Read accessor for the API/dashboard "awaiting consent" surface; currently
|
||||||
|
/// exercised by tests, so allow it to be unused in non-test builds.
|
||||||
|
#[cfg_attr(not(test), allow(dead_code))]
|
||||||
pub async fn get_consent_state(&self, session_id: SessionId) -> Option<ConsentState> {
|
pub async fn get_consent_state(&self, session_id: SessionId) -> Option<ConsentState> {
|
||||||
let sessions = self.sessions.read().await;
|
let sessions = self.sessions.read().await;
|
||||||
sessions.get(&session_id).map(|s| s.info.consent_state)
|
sessions.get(&session_id).map(|s| s.info.consent_state)
|
||||||
@@ -721,7 +724,8 @@ mod tests {
|
|||||||
.register_agent("agent-deny".to_string(), "Deny PC".to_string(), false)
|
.register_agent("agent-deny".to_string(), "Deny PC".to_string(), false)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
mgr.set_consent_state(session_id, ConsentState::Denied).await;
|
mgr.set_consent_state(session_id, ConsentState::Denied)
|
||||||
|
.await;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
mgr.get_consent_state(session_id).await,
|
mgr.get_consent_state(session_id).await,
|
||||||
Some(ConsentState::Denied)
|
Some(ConsentState::Denied)
|
||||||
|
|||||||
Reference in New Issue
Block a user