use std::{env, fs::{remove_file, File, create_dir_all}};
use anyhow::{anyhow, Context, Result};
use camino::Utf8PathBuf;
use edlearn_client::{AuthState, Client, Credentials};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AuthCache {
pub creds: Credentials,
auth_state: AuthState,
}
const FILE_NAME: &str = "learn-tui.json";
impl AuthCache {
pub fn from_client(client: &Client) -> Self {
Self {
auth_state: client.auth_state(),
creds: client.creds.clone(),
}
}
pub fn into_client(self) -> Result<Client> {
Ok(Client::with_auth_state(self.creds, self.auth_state).unwrap())
}
pub fn clear() -> Result<()> {
let Ok(path) = state_file_location() else {
return Ok(()); };
remove_file(path)?;
Ok(())
}
pub fn load() -> Result<Self> {
let path = state_file_location()?;
let file = File::open(path).context("error opening auth cache")?;
let config = serde_json::from_reader(&file).context("error deserialising auth cache")?;
Ok(config)
}
pub fn save(&self) -> Result<()> {
let path = state_file_location()?;
create_dir_all(path.parent().unwrap())?;
let mut file = File::create(path).context("error opening auth cache")?;
serde_json::to_writer(&mut file, &self).context("error deserialising auth cache")?;
Ok(())
}
}
#[cfg(not(target_os = "windows"))]
fn state_file_location() -> Result<Utf8PathBuf> {
let mut out = if let Ok(loc) = env::var("XDG_STATE_DIR") {
Utf8PathBuf::from(loc)
} else {
#[allow(deprecated)]
let mut home = env::home_dir().ok_or_else(|| anyhow!("user home dir not set"))?;
home.push(".local");
home.push(".state");
home.try_into().expect("non utf8 path")
};
out.push(FILE_NAME);
Ok(out)
}
#[cfg(target_os = "windows")]
fn state_file_location() -> Result<Utf8PathBuf> {
let mut out = if let Ok(loc) = env::var("LOCALAPPDATA") {
Utf8PathBuf::from(loc)
} else {
#[allow(deprecated)]
let mut home = env::home_dir().ok_or_else(|| anyhow!("user home dir not set"))?;
home.push("AppData");
home.push("Local");
home.try_into().expect("non utf8 path")
};
out.push(FILE_NAME);
Ok(out)
}
#[derive(Debug)]
pub struct LoginDetails {
pub creds: Credentials,
pub remember: bool,
}