✨ cli + user api
This commit is contained in:
parent
46cf2f4572
commit
b010027549
12 changed files with 504 additions and 25 deletions
src/sheepctl_core
105
src/sheepctl_core/cmd.rs
Normal file
105
src/sheepctl_core/cmd.rs
Normal file
|
@ -0,0 +1,105 @@
|
|||
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");
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue