105 lines
2.7 KiB
Rust
105 lines
2.7 KiB
Rust
use std::path::PathBuf;
|
|
|
|
use owl::{Deserialize, Serialize};
|
|
use sheepd::{DeviceList, LoginParam};
|
|
|
|
use super::args::{ListDevicesCommand, LoginCommand};
|
|
use crate::api::domain;
|
|
|
|
pub fn api_call<T: Serialize + for<'a> Deserialize<'a>, I: Serialize>(
|
|
server: &str,
|
|
path: &str,
|
|
data: I,
|
|
) -> crate::api::Result<T> {
|
|
let url = format!("{}/{path}", domain(server));
|
|
let mut res = ureq::post(url).send_json(data).unwrap();
|
|
let res: crate::api::Result<T> = res.body_mut().read_json().unwrap();
|
|
res
|
|
}
|
|
|
|
pub fn api_call_get<T: Serialize + for<'a> Deserialize<'a>>(
|
|
server: &str,
|
|
path: &str,
|
|
token: &str,
|
|
) -> crate::api::Result<T> {
|
|
let url = format!("{}/{path}", domain(server));
|
|
let mut res = ureq::get(url)
|
|
.header("Authorization", format!("Bearer {token}"))
|
|
.force_send_body()
|
|
.send_empty()
|
|
.unwrap();
|
|
let res: crate::api::Result<T> = res.body_mut().read_json().unwrap();
|
|
res
|
|
}
|
|
|
|
fn get_config_path() -> Option<PathBuf> {
|
|
directories::ProjectDirs::from("de", "Hydrar", "sheepd")
|
|
.map(|proj_dirs| proj_dirs.config_dir().join("config.toml"))
|
|
}
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
pub struct CtlConfig {
|
|
pub home: String,
|
|
pub token: String,
|
|
}
|
|
|
|
impl CtlConfig {
|
|
pub fn load() -> Option<Self> {
|
|
let c = std::fs::read_to_string(get_config_path()?).ok()?;
|
|
toml::from_str(&c).ok()
|
|
}
|
|
|
|
pub fn save(&self) {
|
|
let s = toml::to_string(self).unwrap();
|
|
let config = get_config_path().unwrap();
|
|
let _ = std::fs::create_dir_all(config.parent().unwrap());
|
|
std::fs::write(get_config_path().unwrap(), s).unwrap();
|
|
}
|
|
}
|
|
|
|
pub fn list_devices(arg: ListDevicesCommand) {
|
|
let conf = CtlConfig::load().unwrap();
|
|
|
|
if let Ok(devices) = api_call_get::<DeviceList>(&conf.home, "devices", &conf.token).as_result()
|
|
{
|
|
println!("Hosts:");
|
|
for d in devices.devices {
|
|
println!(
|
|
"- {} [{}]{}",
|
|
d.hostname,
|
|
d.id,
|
|
if d.online { " [ONLINE]" } else { "" }
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn login(arg: LoginCommand) {
|
|
if let Some(conf) = CtlConfig::load() {
|
|
println!("You are already logged in to {}", conf.home);
|
|
std::process::exit(1);
|
|
}
|
|
|
|
let password = inquire::prompt_secret("Password: ").unwrap();
|
|
|
|
// login request
|
|
if let Result::Ok(token) = api_call::<String, _>(
|
|
&arg.home,
|
|
"login",
|
|
LoginParam {
|
|
username: arg.username,
|
|
password: password,
|
|
},
|
|
)
|
|
.as_result()
|
|
{
|
|
// save token to config
|
|
CtlConfig {
|
|
home: arg.home,
|
|
token,
|
|
}
|
|
.save();
|
|
} else {
|
|
println!("Login failed");
|
|
}
|
|
}
|