error handling, coderabbit

This commit is contained in:
lda committed 2026-05-03 15:39:10 +07:00 Verified
1 parent 155458791e
commit 3f8abc1571
33 files changed
+393 -298

No files matched your search

+16 -16
View File
@@ -5,7 +5,7 @@ use axum::response::IntoResponse;
use serde::{Deserialize, Serialize};
use tracing::warn;
use crate::api::json_error;
use crate::api::ApiError;
use crate::runtime::AppState;
use crate::state::{DeviceIdentifierInput, KnownDeviceInput};
@@ -59,7 +59,7 @@ pub struct MergeKnownDeviceRequest {
pub async fn create_known_device(
State(state): State<AppState>,
Json(req): Json<CreateKnownDeviceRequest>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
) -> Result<impl IntoResponse, ApiError> {
let input = KnownDeviceInput {
display_name: req.display_name,
pinned: req.pinned,
@@ -78,7 +78,7 @@ pub async fn create_known_device(
Ok(device) => Ok((StatusCode::CREATED, Json(known_device_response(device)))),
Err(err) => {
warn!(error = %err, "failed to create known device");
Err(json_error(
Err(ApiError::new(
StatusCode::BAD_REQUEST,
"create_known_device_failed",
&err.to_string(),
@@ -89,7 +89,7 @@ pub async fn create_known_device(
pub async fn list_known_devices(
State(state): State<AppState>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
) -> Result<impl IntoResponse, ApiError> {
match state.store.list_known_devices().await {
Ok(devices) => Ok((
StatusCode::OK,
@@ -102,7 +102,7 @@ pub async fn list_known_devices(
)),
Err(err) => {
warn!(error = %err, "failed to list known devices");
Err(json_error(
Err(ApiError::new(
StatusCode::INTERNAL_SERVER_ERROR,
"list_known_devices_failed",
&err.to_string(),
@@ -114,7 +114,7 @@ pub async fn list_known_devices(
pub async fn forget_known_device(
State(state): State<AppState>,
AxumPath(device_id): AxumPath<String>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
) -> Result<impl IntoResponse, ApiError> {
match state.store.forget_known_device(&device_id).await {
Ok(forgotten) => Ok((
StatusCode::OK,
@@ -125,7 +125,7 @@ pub async fn forget_known_device(
)),
Err(err) => {
warn!(error = %err, "failed to forget known device");
Err(json_error(
Err(ApiError::new(
StatusCode::INTERNAL_SERVER_ERROR,
"forget_known_device_failed",
&err.to_string(),
@@ -138,7 +138,7 @@ pub async fn attach_device_identifier(
State(state): State<AppState>,
AxumPath(device_id): AxumPath<String>,
Json(req): Json<DeviceIdentifierRequest>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
) -> Result<impl IntoResponse, ApiError> {
let input = DeviceIdentifierInput {
kind: req.kind,
value: req.value,
@@ -150,14 +150,14 @@ pub async fn attach_device_identifier(
.await
{
Ok(Some(device)) => Ok((StatusCode::OK, Json(known_device_response(device)))),
Ok(None) => Err(json_error(
Ok(None) => Err(ApiError::new(
StatusCode::NOT_FOUND,
"known_device_not_found",
"known device not found",
)),
Err(err) => {
warn!(error = %err, "failed to attach device identifier");
Err(json_error(
Err(ApiError::new(
StatusCode::BAD_REQUEST,
"attach_device_identifier_failed",
&err.to_string(),
@@ -169,21 +169,21 @@ pub async fn attach_device_identifier(
pub async fn detach_device_identifier(
State(state): State<AppState>,
AxumPath((device_id, identifier_key)): AxumPath<(String, String)>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
) -> Result<impl IntoResponse, ApiError> {
match state
.store
.detach_device_identifier(&device_id, &identifier_key)
.await
{
Ok(Some(device)) => Ok((StatusCode::OK, Json(known_device_response(device)))),
Ok(None) => Err(json_error(
Ok(None) => Err(ApiError::new(
StatusCode::NOT_FOUND,
"known_device_not_found",
"known device not found",
)),
Err(err) => {
warn!(error = %err, "failed to detach device identifier");
Err(json_error(
Err(ApiError::new(
StatusCode::BAD_REQUEST,
"detach_device_identifier_failed",
&err.to_string(),
@@ -196,21 +196,21 @@ pub async fn merge_known_device(
State(state): State<AppState>,
AxumPath(device_id): AxumPath<String>,
Json(req): Json<MergeKnownDeviceRequest>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
) -> Result<impl IntoResponse, ApiError> {
match state
.store
.merge_known_devices(&device_id, &req.source_device_id)
.await
{
Ok(Some(device)) => Ok((StatusCode::OK, Json(known_device_response(device)))),
Ok(None) => Err(json_error(
Ok(None) => Err(ApiError::new(
StatusCode::NOT_FOUND,
"known_device_not_found",
"target or source known device not found",
)),
Err(err) => {
warn!(error = %err, "failed to merge known devices");
Err(json_error(
Err(ApiError::new(
StatusCode::BAD_REQUEST,
"merge_known_device_failed",
&err.to_string(),
+13 -13
View File
@@ -5,7 +5,7 @@ use axum::response::IntoResponse;
use serde::{Deserialize, Serialize};
use tracing::{info, warn};
use crate::api::json_error;
use crate::api::ApiError;
use crate::runtime::{AppState, SessionEvent};
use crate::state::AuditEventInput;
@@ -70,7 +70,7 @@ pub async fn healthz() -> &'static str {
pub async fn enroll(
State(state): State<AppState>,
Json(req): Json<EnrollRequest>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
) -> Result<impl IntoResponse, ApiError> {
match state.store.enroll(&req.enroll_token).await {
Ok(issued) => {
info!(agent_id = %issued.agent_id, "agent enrollment accepted");
@@ -119,7 +119,7 @@ pub async fn enroll(
{
warn!(error = %audit_err, "failed to append audit event for enroll rejection");
}
Err(json_error(
Err(ApiError::new(
StatusCode::UNAUTHORIZED,
"enrollment_rejected",
&err.to_string(),
@@ -131,7 +131,7 @@ pub async fn enroll(
pub async fn issue_enroll_token(
State(state): State<AppState>,
Query(query): Query<IssueEnrollTokenQuery>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
) -> Result<impl IntoResponse, ApiError> {
let ttl = std::time::Duration::from_secs(
query
.ttl_seconds
@@ -175,7 +175,7 @@ pub async fn issue_enroll_token(
}
Err(err) => {
warn!(error = %err, "failed to issue enroll token");
Err(json_error(
Err(ApiError::new(
StatusCode::INTERNAL_SERVER_ERROR,
"issue_enroll_token_failed",
&err.to_string(),
@@ -186,7 +186,7 @@ pub async fn issue_enroll_token(
pub async fn list_enroll_tokens(
State(state): State<AppState>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
) -> Result<impl IntoResponse, ApiError> {
match state.store.list_enroll_tokens().await {
Ok(tokens) => {
if let Err(err) = state
@@ -220,7 +220,7 @@ pub async fn list_enroll_tokens(
}
Err(err) => {
warn!(error = %err, "failed to list enroll tokens");
Err(json_error(
Err(ApiError::new(
StatusCode::INTERNAL_SERVER_ERROR,
"list_enroll_tokens_failed",
&err.to_string(),
@@ -232,7 +232,7 @@ pub async fn list_enroll_tokens(
pub async fn revoke_enroll_token(
State(state): State<AppState>,
AxumPath(token): AxumPath<String>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
) -> Result<impl IntoResponse, ApiError> {
match state.store.revoke_enroll_token(&token).await {
Ok(revoked) => {
if let Err(err) = state
@@ -267,7 +267,7 @@ pub async fn revoke_enroll_token(
}
Err(err) => {
warn!(error = %err, "failed to revoke enroll token");
Err(json_error(
Err(ApiError::new(
StatusCode::INTERNAL_SERVER_ERROR,
"revoke_enroll_token_failed",
&err.to_string(),
@@ -279,7 +279,7 @@ pub async fn revoke_enroll_token(
pub async fn revoke_agent(
State(state): State<AppState>,
AxumPath(agent_id): AxumPath<String>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
) -> Result<impl IntoResponse, ApiError> {
match state.store.revoke_agent(&agent_id).await {
Ok(revoked) => {
if revoked {
@@ -322,7 +322,7 @@ pub async fn revoke_agent(
}
Err(err) => {
warn!(error = %err, "failed to revoke agent credentials");
Err(json_error(
Err(ApiError::new(
StatusCode::INTERNAL_SERVER_ERROR,
"revoke_agent_failed",
&err.to_string(),
@@ -335,7 +335,7 @@ pub async fn set_agent_nickname(
State(state): State<AppState>,
AxumPath(agent_id): AxumPath<String>,
Json(req): Json<SetAgentNicknameRequest>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
) -> Result<impl IntoResponse, ApiError> {
let normalized = req
.nickname
.as_deref()
@@ -389,7 +389,7 @@ pub async fn set_agent_nickname(
}
Err(err) => {
warn!(error = %err, "failed to update agent nickname");
Err(json_error(
Err(ApiError::new(
StatusCode::INTERNAL_SERVER_ERROR,
"set_agent_nickname_failed",
&err.to_string(),
@@ -7,8 +7,8 @@ use axum::response::IntoResponse;
use tracing::warn;
use wakey_agent::protocol::{AgentCommand, InventoryRequest, WakeRequest};
use crate::api::ApiError;
use crate::api::commands::relay_agent_command;
use crate::api::json_error;
use crate::runtime::AppState;
mod build;
@@ -29,12 +29,12 @@ use types::{
pub async fn list_fleet_devices(
State(state): State<AppState>,
Query(query): Query<ListFleetDevicesQuery>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
) -> Result<impl IntoResponse, ApiError> {
match load_fleet_devices(&state, &query).await {
Ok(devices) => Ok((StatusCode::OK, Json(devices))),
Err(err) => {
warn!(error = %err, "failed to list fleet devices");
Err(json_error(
Err(ApiError::new(
StatusCode::INTERNAL_SERVER_ERROR,
"list_fleet_devices_failed",
&err.to_string(),
@@ -46,7 +46,7 @@ pub async fn list_fleet_devices(
pub async fn refresh_fleet_devices(
State(state): State<AppState>,
Json(req): Json<RefreshFleetDevicesRequest>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
) -> Result<impl IntoResponse, ApiError> {
let mut agent_ids = if req.agent_ids.is_empty() {
let sessions = state.sessions.read().await;
sessions.keys().cloned().collect::<Vec<_>>()
@@ -131,11 +131,11 @@ pub async fn refresh_fleet_devices(
.map(|error| error.message)
.or_else(|| Some("inventory command failed".into())),
}),
Err((status, body)) => results.push(RefreshFleetAgentResult {
Err(err) => results.push(RefreshFleetAgentResult {
agent_id,
status: "error".into(),
accepted: 0,
error: Some(format!("{status}: {}", body.0)),
error: Some(format!("{}: {}", err.status, err.message)),
}),
}
}
@@ -152,7 +152,7 @@ pub async fn refresh_fleet_devices(
pub async fn wake_fleet_device(
State(state): State<AppState>,
Json(req): Json<WakeFleetDeviceRequest>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
) -> Result<impl IntoResponse, ApiError> {
let query = ListFleetDevicesQuery {
query: None,
presence: None,
@@ -163,7 +163,7 @@ pub async fn wake_fleet_device(
};
let devices = load_fleet_devices(&state, &query).await.map_err(|err| {
warn!(error = %err, "failed loading fleet devices for wake");
json_error(
ApiError::new(
StatusCode::INTERNAL_SERVER_ERROR,
"load_fleet_devices_failed",
&err.to_string(),
@@ -174,7 +174,7 @@ pub async fn wake_fleet_device(
.into_iter()
.find(|device| device.device_key == req.device_key)
.ok_or_else(|| {
json_error(
ApiError::new(
StatusCode::NOT_FOUND,
"fleet_device_not_found",
"fleet device not found",
@@ -189,7 +189,7 @@ pub async fn wake_fleet_device(
None => device.recommended_route,
}
.ok_or_else(|| {
json_error(
ApiError::new(
StatusCode::BAD_REQUEST,
"wake_route_unavailable",
"no wakeable connected MAC-backed route is available",
@@ -197,21 +197,21 @@ pub async fn wake_fleet_device(
})?;
let Some(mac) = route.mac else {
return Err(json_error(
return Err(ApiError::new(
StatusCode::BAD_REQUEST,
"wake_route_unavailable",
"selected route does not include a MAC address",
));
};
if !route.connected {
return Err(json_error(
return Err(ApiError::new(
StatusCode::BAD_REQUEST,
"wake_route_unavailable",
"selected route agent is not connected",
));
}
if !route.wakeable {
return Err(json_error(
return Err(ApiError::new(
StatusCode::BAD_REQUEST,
"wake_route_unavailable",
"selected route is not wakeable",
+3 -5
View File
@@ -5,7 +5,7 @@ use axum::response::IntoResponse;
use serde::{Deserialize, Serialize};
use tracing::warn;
use crate::api::json_error;
use crate::api::ApiError;
use crate::runtime::AppState;
#[derive(Debug, Serialize, Deserialize)]
@@ -17,9 +17,7 @@ pub struct StateStatsResponse {
pub expired_enroll_token_count: usize,
}
pub async fn state_stats(
State(state): State<AppState>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
pub async fn state_stats(State(state): State<AppState>) -> Result<impl IntoResponse, ApiError> {
match state.store.stats().await {
Ok(stats) => Ok((
StatusCode::OK,
@@ -33,7 +31,7 @@ pub async fn state_stats(
)),
Err(err) => {
warn!(error = %err, "failed to read state stats");
Err(json_error(
Err(ApiError::new(
StatusCode::INTERNAL_SERVER_ERROR,
"state_stats_failed",
&err.to_string(),