feat(cli): D-Bus client wrapper + full subcommand dispatcher
Lands plan tasks C2 (Daemon proxy wrapping all 9 D-Bus methods via Proxy::new_owned), C3 (status/list/policy-show), C4 (enroll/remove/policy- set/apply/validate), and C5 (pending/recovery). Bundled because dispatch needs the bus wrapper to compile cleanly under -D warnings. Phase 4/5/12 placeholders in the dispatcher: policy apply re-saves to trigger PolicyChanged; policy validate is a TOML round-trip; pending list and recovery list are no-op messages until the corresponding D-Bus methods land. 5 clap-parser tests pass (was 5; same — parser shape unchanged in this commit). Workspace clippy clean.
This commit is contained in:
@@ -1,2 +1,59 @@
|
||||
// Phase 3+6+7 plan: D-Bus client wrapper. Stubbed in Task C1; real methods
|
||||
// land in Task C2.
|
||||
//! Thin async D-Bus wrapper around `io.dangerousthings.AuthForge1`. Each method
|
||||
//! is one `Proxy::call` round-trip. Connection + proxy hold owned state so the
|
||||
//! Daemon handle can be passed around freely.
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use authforge_common::policy::Policy;
|
||||
use authforge_common::types::{Credential, PendingFlag, PolicyApplyResult};
|
||||
|
||||
const BUS_NAME: &str = "io.dangerousthings.AuthForge";
|
||||
const OBJECT_PATH: &str = "/io/dangerousthings/AuthForge";
|
||||
const IFACE: &str = "io.dangerousthings.AuthForge1";
|
||||
|
||||
pub(crate) struct Daemon {
|
||||
proxy: zbus::Proxy<'static>,
|
||||
}
|
||||
|
||||
impl Daemon {
|
||||
pub async fn connect() -> Result<Self> {
|
||||
let conn = zbus::Connection::system()
|
||||
.await
|
||||
.context("connecting to system D-Bus")?;
|
||||
let proxy = zbus::Proxy::new_owned(conn, BUS_NAME, OBJECT_PATH, IFACE)
|
||||
.await
|
||||
.context("constructing AuthForge proxy")?;
|
||||
Ok(Self { proxy })
|
||||
}
|
||||
|
||||
pub async fn list_credentials(&self, user: &str) -> Result<Vec<Credential>> {
|
||||
Ok(self.proxy.call("ListCredentials", &(user,)).await?)
|
||||
}
|
||||
|
||||
pub async fn enroll_own(&self, user: &str, nickname: &str) -> Result<Credential> {
|
||||
Ok(self.proxy.call("EnrollOwn", &(user, nickname)).await?)
|
||||
}
|
||||
|
||||
pub async fn remove_own(&self, user: &str, cred_id: &str) -> Result<()> {
|
||||
Ok(self.proxy.call("RemoveOwn", &(user, cred_id)).await?)
|
||||
}
|
||||
|
||||
pub async fn get_policy(&self) -> Result<Policy> {
|
||||
Ok(self.proxy.call("GetPolicy", &()).await?)
|
||||
}
|
||||
|
||||
pub async fn set_policy(&self, p: &Policy) -> Result<PolicyApplyResult> {
|
||||
Ok(self.proxy.call("SetPolicy", &(p,)).await?)
|
||||
}
|
||||
|
||||
pub async fn set_pending_flag(&self, user: &str, flag: &PendingFlag) -> Result<()> {
|
||||
Ok(self.proxy.call("SetPendingFlag", &(user, flag)).await?)
|
||||
}
|
||||
|
||||
pub async fn clear_pending_flag(&self, user: &str) -> Result<()> {
|
||||
Ok(self.proxy.call("ClearPendingFlag", &(user,)).await?)
|
||||
}
|
||||
|
||||
pub async fn generate_recovery_code(&self, user: &str) -> Result<String> {
|
||||
Ok(self.proxy.call("GenerateRecoveryCode", &(user,)).await?)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user