use async_trait::async_trait;
use serde::Deserialize;
use std::process::Command;
use super::AuthProvider;
#[derive(Debug, Deserialize)]
#[serde(tag = "type")]
enum AuthEvent {
#[serde(rename = "secret")]
Secret {
#[allow(dead_code)]
path: String,
value: String,
},
#[serde(rename = "error")]
Error {
message: String,
},
}
pub struct YamlAuthProvider {
auth_port: u16,
}
impl YamlAuthProvider {
pub fn new() -> anyhow::Result<Self> {
Ok(Self {
auth_port: 4445,
})
}
pub fn with_port(port: u16) -> anyhow::Result<Self> {
Ok(Self {
auth_port: port,
})
}
}
#[async_trait]
impl AuthProvider for YamlAuthProvider {
async fn get_secret(&self, key: &str) -> anyhow::Result<Option<String>> {
let output = Command::new("synapse")
.args(&[
"--raw",
"secrets",
"auth",
"get_secret",
"--secret-key",
key,
])
.output()?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
if stderr.contains("Secret not found") || stderr.contains("Not found") {
return Ok(None);
}
return Err(anyhow::anyhow!("Failed to get secret from auth hub: {}", stderr));
}
let stdout = String::from_utf8_lossy(&output.stdout);
let event: AuthEvent = serde_json::from_str(stdout.trim())
.map_err(|e| anyhow::anyhow!("Failed to parse auth response: {}", e))?;
match event {
AuthEvent::Secret { value, .. } => Ok(Some(value)),
AuthEvent::Error { message } => {
if message.contains("not found") {
Ok(None)
} else {
Err(anyhow::anyhow!("Auth error: {}", message))
}
}
}
}
}