54 lines
2.0 KiB
Rust
54 lines
2.0 KiB
Rust
//! Strategy resolver for the heartbeat path. The actual SQL lives in
|
|
//! `Database::strategy_resolve_for` — this module exists to give the
|
|
//! heartbeat handler a stable import surface and to centralize how a
|
|
//! resolved strategy is converted into the wire-shape JSON the client
|
|
//! expects (`strategy.config_options` + `strategy.extra` per
|
|
//! CONSOLE_API.md §6.1).
|
|
|
|
use crate::api::state::AppState;
|
|
use crate::database::ResolvedStrategy;
|
|
use serde_json::{json, Value};
|
|
|
|
/// Resolve and serialize a strategy for `peer_id`. Returns
|
|
/// `(modified_at, strategy_value)` where `strategy_value` is the JSON object
|
|
/// the heartbeat reply embeds under `strategy`. When no strategy applies, we
|
|
/// return an empty `{config_options: {}, extra: {}}` and `modified_at = 0`.
|
|
pub async fn resolve_for(state: &AppState, peer_id: &str) -> (i64, Value) {
|
|
let resolved = state
|
|
.db
|
|
.strategy_resolve_for(peer_id)
|
|
.await
|
|
.unwrap_or_default();
|
|
serialize(&resolved)
|
|
}
|
|
|
|
fn serialize(r: &ResolvedStrategy) -> (i64, Value) {
|
|
let cfg: Value = serde_json::from_str(&r.config_options_json).unwrap_or_else(|_| json!({}));
|
|
let extra: Value = serde_json::from_str(&r.extra_json).unwrap_or_else(|_| json!({}));
|
|
(
|
|
r.modified_at,
|
|
json!({
|
|
"config_options": cfg,
|
|
"extra": extra,
|
|
}),
|
|
)
|
|
}
|
|
|
|
/// `true` iff the resolved strategy for `peer_id` carries
|
|
/// `config_options."enable-remote-exec" = "Y"`. Default is `false` (no
|
|
/// strategy assigned, or strategy didn't set the key) — exec is opt-in
|
|
/// per the design in docs/AGENT-API-AUTH.md.
|
|
pub async fn allows_remote_exec(state: &AppState, peer_id: &str) -> bool {
|
|
let resolved = state
|
|
.db
|
|
.strategy_resolve_for(peer_id)
|
|
.await
|
|
.unwrap_or_default();
|
|
let cfg: Value = serde_json::from_str(&resolved.config_options_json)
|
|
.unwrap_or_else(|_| json!({}));
|
|
cfg.get("enable-remote-exec")
|
|
.and_then(|v| v.as_str())
|
|
.map(|s| s.eq_ignore_ascii_case("Y"))
|
|
.unwrap_or(false)
|
|
}
|