102 lines
3.0 KiB
Rust
102 lines
3.0 KiB
Rust
// src/config/storage/storage.rs
|
|
use serde::{Deserialize, Serialize};
|
|
use std::fs::{self, File};
|
|
use std::io::Write;
|
|
use std::path::PathBuf;
|
|
use anyhow::{Context, Result};
|
|
use tracing::{error, info};
|
|
|
|
#[cfg(unix)]
|
|
use std::os::unix::fs::PermissionsExt;
|
|
|
|
pub const APP_NAME: &str = "KompAC_client";
|
|
pub const TOKEN_FILE_NAME: &str = "auth.token";
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
pub struct StoredAuthData {
|
|
pub access_token: String,
|
|
pub user_id: String,
|
|
pub role: String,
|
|
pub username: String,
|
|
}
|
|
|
|
pub fn get_token_storage_path() -> Result<PathBuf> {
|
|
let state_dir = dirs::state_dir()
|
|
.or_else(|| dirs::home_dir().map(|home| home.join(".local").join("state")))
|
|
.ok_or_else(|| anyhow::anyhow!("Could not determine state directory"))?;
|
|
|
|
let app_state_dir = state_dir.join(APP_NAME);
|
|
fs::create_dir_all(&app_state_dir)
|
|
.with_context(|| format!("Failed to create app state directory at {:?}", app_state_dir))?;
|
|
|
|
Ok(app_state_dir.join(TOKEN_FILE_NAME))
|
|
}
|
|
|
|
pub fn save_auth_data(data: &StoredAuthData) -> Result<()> {
|
|
let path = get_token_storage_path()?;
|
|
|
|
let json_data = serde_json::to_string(data)
|
|
.context("Failed to serialize auth data")?;
|
|
|
|
let mut file = File::create(&path)
|
|
.with_context(|| format!("Failed to create token file at {:?}", path))?;
|
|
|
|
file.write_all(json_data.as_bytes())
|
|
.context("Failed to write token data to file")?;
|
|
|
|
// Set file permissions to 600 (owner read/write only) on Unix
|
|
#[cfg(unix)]
|
|
{
|
|
file.set_permissions(std::fs::Permissions::from_mode(0o600))
|
|
.context("Failed to set token file permissions")?;
|
|
}
|
|
|
|
info!("Auth data saved to {:?}", path);
|
|
Ok(())
|
|
}
|
|
|
|
pub fn load_auth_data() -> Result<Option<StoredAuthData>> {
|
|
let path = get_token_storage_path()?;
|
|
|
|
if !path.exists() {
|
|
info!("Token file not found at {:?}", path);
|
|
return Ok(None);
|
|
}
|
|
|
|
let json_data = fs::read_to_string(&path)
|
|
.with_context(|| format!("Failed to read token file at {:?}", path))?;
|
|
|
|
if json_data.trim().is_empty() {
|
|
info!("Token file is empty at {:?}", path);
|
|
return Ok(None);
|
|
}
|
|
|
|
match serde_json::from_str::<StoredAuthData>(&json_data) {
|
|
Ok(data) => {
|
|
info!("Auth data loaded from {:?}", path);
|
|
Ok(Some(data))
|
|
}
|
|
Err(e) => {
|
|
error!("Failed to deserialize token data from {:?}: {}. Deleting corrupt file.", path, e);
|
|
if let Err(del_e) = fs::remove_file(&path) {
|
|
error!("Failed to delete corrupt token file: {}", del_e);
|
|
}
|
|
Ok(None)
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn delete_auth_data() -> Result<()> {
|
|
let path = get_token_storage_path()?;
|
|
|
|
if path.exists() {
|
|
fs::remove_file(&path)
|
|
.with_context(|| format!("Failed to delete token file at {:?}", path))?;
|
|
info!("Token file deleted from {:?}", path);
|
|
} else {
|
|
info!("Token file not found for deletion at {:?}", path);
|
|
}
|
|
|
|
Ok(())
|
|
}
|