sync: Auto-sync from DESKTOP-0O8A1RL at 2026-04-02 19:20:43
Synced files: - Session logs updated - Latest context and credentials - Command/directive updates Machine: DESKTOP-0O8A1RL Timestamp: 2026-04-02 19:20:43 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -160,3 +160,100 @@ pub async fn get_command(
|
||||
|
||||
Ok(Json(command))
|
||||
}
|
||||
|
||||
/// Delete a single command by ID
|
||||
/// Requires authentication.
|
||||
pub async fn delete_command(
|
||||
State(state): State<AppState>,
|
||||
_user: AuthUser,
|
||||
Path(command_id): Path<Uuid>,
|
||||
) -> Result<StatusCode, (StatusCode, String)> {
|
||||
let deleted = db::delete_command(&state.db, command_id)
|
||||
.await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||||
|
||||
if deleted {
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
} else {
|
||||
Err((StatusCode::NOT_FOUND, "Command not found".to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Cancel response payload
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct CancelCommandResponse {
|
||||
pub status: String,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
/// Cancel a pending or running command
|
||||
/// Requires authentication.
|
||||
pub async fn cancel_command(
|
||||
State(state): State<AppState>,
|
||||
_user: AuthUser,
|
||||
Path(command_id): Path<Uuid>,
|
||||
) -> Result<Json<CancelCommandResponse>, (StatusCode, String)> {
|
||||
let command = db::get_command_by_id(&state.db, command_id)
|
||||
.await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?
|
||||
.ok_or((StatusCode::NOT_FOUND, "Command not found".to_string()))?;
|
||||
|
||||
match command.status.as_str() {
|
||||
"completed" | "failed" | "cancelled" => {
|
||||
return Err((
|
||||
StatusCode::BAD_REQUEST,
|
||||
"Command already finished".to_string(),
|
||||
));
|
||||
}
|
||||
"running" => {
|
||||
// Update status in DB
|
||||
db::cancel_command(&state.db, command_id)
|
||||
.await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||||
|
||||
// Optionally try to send a cancel signal via WebSocket
|
||||
let agents = state.agents.read().await;
|
||||
if agents.is_connected(&command.agent_id) {
|
||||
let cancel_msg = ServerMessage::Error {
|
||||
code: "command_cancelled".to_string(),
|
||||
message: format!("Command {} has been cancelled", command_id),
|
||||
};
|
||||
let _ = agents.send_to(&command.agent_id, cancel_msg).await;
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
// Pending or any other status - just update DB
|
||||
db::cancel_command(&state.db, command_id)
|
||||
.await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Json(CancelCommandResponse {
|
||||
status: "cancelled".to_string(),
|
||||
message: "Command cancelled".to_string(),
|
||||
}))
|
||||
}
|
||||
|
||||
/// Clear history response payload
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct ClearHistoryResponse {
|
||||
pub deleted: u64,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
/// Bulk clear finished commands (completed, failed, cancelled)
|
||||
/// Requires authentication.
|
||||
pub async fn clear_command_history(
|
||||
State(state): State<AppState>,
|
||||
_user: AuthUser,
|
||||
) -> Result<Json<ClearHistoryResponse>, (StatusCode, String)> {
|
||||
let count = db::delete_finished_commands(&state.db)
|
||||
.await
|
||||
.map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
|
||||
|
||||
Ok(Json(ClearHistoryResponse {
|
||||
deleted: count,
|
||||
message: format!("Cleared {} commands from history", count),
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -56,8 +56,9 @@ pub fn routes() -> Router<AppState> {
|
||||
.route("/metrics/summary", get(metrics::get_summary))
|
||||
// Commands
|
||||
.route("/agents/:id/command", post(commands::send_command))
|
||||
.route("/commands", get(commands::list_commands))
|
||||
.route("/commands/:id", get(commands::get_command))
|
||||
.route("/commands", get(commands::list_commands).delete(commands::clear_command_history))
|
||||
.route("/commands/:id", get(commands::get_command).delete(commands::delete_command))
|
||||
.route("/commands/:id/cancel", post(commands::cancel_command))
|
||||
// Legacy Agent (PowerShell for 2008 R2)
|
||||
.route("/agent/register-legacy", post(agents::register_legacy))
|
||||
.route("/agent/heartbeat", post(agents::heartbeat))
|
||||
|
||||
Reference in New Issue
Block a user