use super::{
common::send_authd_request,
constants::{SN_AUTHD_ENDPOINT_HOST, SN_AUTHD_ENDPOINT_PORT},
Safe,
};
use crate::{
ipc::{IpcMsg, IpcResp},
Error, Result,
};
use sn_interface::types::Keypair;
use serde_json::json;
use std::path::{Path, PathBuf};
use tracing::{debug, info};
const SN_AUTHD_METHOD_AUTHORISE: &str = "authorise";
impl Safe {
pub async fn auth_app(
app_id: &str,
app_name: &str,
app_vendor: &str,
endpoint: Option<&str>,
authd_cert_path: impl AsRef<Path>,
) -> Result<Keypair> {
info!("Sending authorisation request to SAFE Authenticator...");
let request = IpcMsg::new_auth_req(app_id, app_name, app_vendor);
let auth_req_str = request.to_string()?;
debug!(
"Authorisation request generated successfully: {}",
auth_req_str
);
let auth_res = send_app_auth_req(
&auth_req_str,
endpoint,
&PathBuf::from(authd_cert_path.as_ref()),
)
.await?;
match IpcMsg::from_string(&auth_res) {
Ok(IpcMsg::Resp(IpcResp::Auth(Ok(auth_granted)))) => {
info!("Application '{}' was authorised!", app_id);
Ok(auth_granted.app_keypair)
}
Ok(other) => {
info!("Unexpected messages received: {:?}", other);
Err(Error::AuthError(format!(
"Application was not authorised, unexpected response was received: {other:?}",
)))
}
Err(e) => {
info!("Application '{}' was not authorised", app_id);
Err(Error::AuthError(format!(
"Application '{app_id}' was not authorised: {e:?}",
)))
}
}
}
}
async fn send_app_auth_req(
auth_req_str: &str,
endpoint: Option<&str>,
authd_cert_path: &Path,
) -> Result<String> {
let authd_service_url = match endpoint {
None => format!("{SN_AUTHD_ENDPOINT_HOST}:{SN_AUTHD_ENDPOINT_PORT}"),
Some(endpoint) => endpoint.to_string(),
};
info!("Sending authorisation request to SAFE Authenticator...");
let authd_response = send_authd_request::<String>(
authd_cert_path,
&authd_service_url,
SN_AUTHD_METHOD_AUTHORISE,
json!(auth_req_str),
)
.await?;
info!("SAFE authorisation response received!");
Ok(authd_response)
}