This commit is contained in:
lda committed 2026-04-14 06:03:06 +07:00
1 parent 8948171ae7
commit f034fc5afd
11 files changed
+303 -18

No files matched your search

+4 -2
View File
@@ -16,6 +16,7 @@ use crate::state::AuditEventInput;
pub struct AgentStatus {
pub agent_id: String,
pub connected: bool,
pub nickname: Option<String>,
}
#[derive(Debug, Deserialize)]
@@ -37,14 +38,15 @@ pub struct RelayCommandResponse {
pub async fn list_agents(
State(state): State<AppState>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
let enrolled = state.store.list_agents().await;
let enrolled = state.store.list_agents_with_nicknames().await;
let sessions = state.sessions.read().await;
let agents = enrolled
.into_iter()
.map(|agent_id| AgentStatus {
.map(|(agent_id, nickname)| AgentStatus {
connected: sessions.contains_key(&agent_id),
agent_id,
nickname,
})
.collect::<Vec<_>>();
+79
View File
@@ -56,6 +56,18 @@ pub struct RevokeAgentResponse {
pub revoked: bool,
}
#[derive(Debug, Deserialize)]
pub struct SetAgentNicknameRequest {
pub nickname: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct SetAgentNicknameResponse {
pub agent_id: String,
pub nickname: Option<String>,
pub updated: bool,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct StateStatsResponse {
pub db_path: String,
@@ -336,6 +348,73 @@ pub async fn revoke_agent(
}
}
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>)> {
let normalized = req
.nickname
.as_deref()
.map(str::trim)
.filter(|v| !v.is_empty())
.map(ToOwned::to_owned);
match state
.store
.set_agent_nickname(&agent_id, normalized.as_deref())
.await
{
Ok(updated) => {
if let Err(err) = state
.store
.append_audit_event(AuditEventInput {
actor_type: "admin_api".into(),
actor_id: None,
agent_id: Some(agent_id.clone()),
request_id: None,
event_type: "agent_nickname_set".into(),
outcome: if updated {
"ok".into()
} else {
"not_found".into()
},
latency_ms: None,
message: if updated {
"updated agent nickname".into()
} else {
"agent not found for nickname update".into()
},
metadata: serde_json::json!({
"agent_id": agent_id,
"nickname": normalized,
}),
})
.await
{
warn!(error = %err, "failed to append audit event for nickname set");
}
Ok((
StatusCode::OK,
Json(SetAgentNicknameResponse {
agent_id,
nickname: normalized,
updated,
}),
))
}
Err(err) => {
warn!(error = %err, "failed to update agent nickname");
Err(json_error(
StatusCode::INTERNAL_SERVER_ERROR,
"set_agent_nickname_failed",
&err.to_string(),
))
}
}
}
pub async fn state_stats(
State(state): State<AppState>,
) -> Result<impl IntoResponse, (StatusCode, Json<serde_json::Value>)> {
+1 -1
View File
@@ -12,7 +12,7 @@ pub use commands::{list_agents, run_command};
pub use control::{
EnrollTokenStatus, IssueEnrollTokenResponse, RevokeAgentResponse, RevokeEnrollTokenResponse,
StateStatsResponse, enroll, healthz, issue_enroll_token, list_enroll_tokens, revoke_agent,
revoke_enroll_token, state_stats,
revoke_enroll_token, set_agent_nickname, state_stats,
};
pub fn json_error(