224 lines
6.8 KiB
Rust
224 lines
6.8 KiB
Rust
#![allow(dead_code)]
|
|
|
|
use crate::error::{AppError, AppResult};
|
|
use serde::{Deserialize, Serialize};
|
|
use std::path::PathBuf;
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct AppConfig {
|
|
pub backend_base_url: String,
|
|
pub mdm_server_url: String,
|
|
pub supabase_url: String,
|
|
pub supabase_anon_key: String,
|
|
/// Stable device identity known to the backend (UserDevice.deviceId).
|
|
/// Filled after first successful device registration.
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub device_id: Option<String>,
|
|
/// Hardware-bound identity (UserDevice.hardwareId).
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub hardware_id: Option<String>,
|
|
}
|
|
|
|
impl Default for AppConfig {
|
|
fn default() -> Self {
|
|
Self {
|
|
backend_base_url: "https://staging.rebreak.org".to_string(),
|
|
mdm_server_url: "https://mdm.rebreak.org".to_string(),
|
|
supabase_url: String::new(),
|
|
supabase_anon_key: String::new(),
|
|
device_id: None,
|
|
hardware_id: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
const KEYRING_SERVICE: &str = "org.rebreak.magic";
|
|
const KEYRING_ACCOUNT: &str = "magic-session";
|
|
const SESSION_FILE: &str = "session.json";
|
|
const DESKTOP_PROTECTION_FILE: &str = "desktop-protection.json";
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct MagicSession {
|
|
pub access_token: String,
|
|
pub session_id: String,
|
|
pub user_id: String,
|
|
#[serde(with = "chrono::serde::ts_seconds")]
|
|
pub created_at: chrono::DateTime<chrono::Utc>,
|
|
pub label: Option<String>,
|
|
}
|
|
|
|
impl MagicSession {
|
|
pub fn new(access_token: String, session_id: String, label: Option<String>) -> Self {
|
|
Self {
|
|
access_token,
|
|
session_id,
|
|
user_id: String::new(),
|
|
created_at: chrono::Utc::now(),
|
|
label,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct BinderConfig {
|
|
#[serde(rename = "mdmServer")]
|
|
pub mdm_server: String,
|
|
#[serde(rename = "mdmUser")]
|
|
pub mdm_user: String,
|
|
#[serde(rename = "mdmApiKey")]
|
|
pub mdm_api_key: String,
|
|
}
|
|
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct DesktopProtectionState {
|
|
pub active: bool,
|
|
pub platform: String,
|
|
#[serde(with = "chrono::serde::ts_seconds")]
|
|
pub activated_at: chrono::DateTime<chrono::Utc>,
|
|
}
|
|
|
|
impl AppConfig {
|
|
pub fn config_dir() -> AppResult<PathBuf> {
|
|
let dir = dirs::config_dir()
|
|
.ok_or_else(|| AppError::new("Could not find config directory"))?
|
|
.join("org.rebreak.magic");
|
|
std::fs::create_dir_all(&dir)?;
|
|
Ok(dir)
|
|
}
|
|
|
|
pub fn config_path() -> AppResult<PathBuf> {
|
|
Ok(Self::config_dir()?.join("config.json"))
|
|
}
|
|
|
|
pub fn binder_config_path() -> AppResult<PathBuf> {
|
|
Ok(dirs::config_dir()
|
|
.ok_or_else(|| AppError::new("Could not find config directory"))?
|
|
.join("rebreak-binder")
|
|
.join("config.json"))
|
|
}
|
|
|
|
pub fn load_binder_config() -> AppResult<BinderConfig> {
|
|
let path = Self::binder_config_path()?;
|
|
if !path.exists() {
|
|
return Err(AppError::new(
|
|
"rebreak-binder config nicht gefunden. Bitte README → 'Config (lokal)'.".to_string(),
|
|
));
|
|
}
|
|
let json = std::fs::read_to_string(&path)?;
|
|
serde_json::from_str(&json)
|
|
.map_err(|e| AppError::new(format!("rebreak-binder config kaputt: {}", e)))
|
|
}
|
|
|
|
pub fn load() -> Self {
|
|
match Self::config_path() {
|
|
Ok(path) if path.exists() => {
|
|
std::fs::read_to_string(&path)
|
|
.ok()
|
|
.and_then(|s| serde_json::from_str(&s).ok())
|
|
.unwrap_or_default()
|
|
}
|
|
_ => Self::default(),
|
|
}
|
|
}
|
|
|
|
pub fn save(&self) -> AppResult<()> {
|
|
let path = Self::config_path()?;
|
|
let contents = serde_json::to_string_pretty(self)?;
|
|
std::fs::write(path, contents)?;
|
|
Ok(())
|
|
}
|
|
|
|
fn session_path() -> AppResult<PathBuf> {
|
|
Ok(Self::config_dir()?.join(SESSION_FILE))
|
|
}
|
|
|
|
pub fn save_magic_session(session: &MagicSession) -> AppResult<()> {
|
|
let path = Self::session_path()?;
|
|
let json = serde_json::to_string_pretty(session)
|
|
.map_err(|e| AppError::new(format!("Failed to serialize session: {}", e)))?;
|
|
std::fs::write(&path, json)?;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn load_magic_session() -> AppResult<Option<MagicSession>> {
|
|
let path = match Self::session_path() {
|
|
Ok(p) => p,
|
|
Err(_) => return Ok(None),
|
|
};
|
|
|
|
if !path.exists() {
|
|
return Ok(None);
|
|
}
|
|
|
|
let json = std::fs::read_to_string(&path)?;
|
|
if json.trim().is_empty() {
|
|
return Ok(None);
|
|
}
|
|
|
|
let session = serde_json::from_str(&json)
|
|
.map_err(|e| AppError::new(format!("Failed to parse session: {}", e)))?;
|
|
Ok(Some(session))
|
|
}
|
|
|
|
pub fn clear_magic_session() -> AppResult<()> {
|
|
let path = match Self::session_path() {
|
|
Ok(p) => p,
|
|
Err(_) => return Ok(()),
|
|
};
|
|
if path.exists() {
|
|
std::fs::remove_file(&path)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn desktop_protection_path() -> AppResult<PathBuf> {
|
|
Ok(Self::config_dir()?.join(DESKTOP_PROTECTION_FILE))
|
|
}
|
|
|
|
pub fn save_desktop_protection(state: &DesktopProtectionState) -> AppResult<()> {
|
|
let path = Self::desktop_protection_path()?;
|
|
let json = serde_json::to_string_pretty(state)
|
|
.map_err(|e| AppError::new(format!("Failed to serialize desktop protection state: {}", e)))?;
|
|
std::fs::write(&path, json)?;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn load_desktop_protection() -> AppResult<Option<DesktopProtectionState>> {
|
|
let path = match Self::desktop_protection_path() {
|
|
Ok(p) => p,
|
|
Err(_) => return Ok(None),
|
|
};
|
|
if !path.exists() {
|
|
return Ok(None);
|
|
}
|
|
let json = std::fs::read_to_string(&path)?;
|
|
if json.trim().is_empty() {
|
|
return Ok(None);
|
|
}
|
|
let state = serde_json::from_str(&json)
|
|
.map_err(|e| AppError::new(format!("Failed to parse desktop protection state: {}", e)))?;
|
|
Ok(Some(state))
|
|
}
|
|
|
|
pub fn clear_desktop_protection() -> AppResult<()> {
|
|
let path = match Self::desktop_protection_path() {
|
|
Ok(p) => p,
|
|
Err(_) => return Ok(()),
|
|
};
|
|
if path.exists() {
|
|
std::fs::remove_file(&path)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub fn set_device_id(&mut self, id: String) -> AppResult<()> {
|
|
self.device_id = Some(id);
|
|
self.save()
|
|
}
|
|
|
|
pub fn set_hardware_id(&mut self, id: String) -> AppResult<()> {
|
|
self.hardware_id = Some(id);
|
|
self.save()
|
|
}
|
|
}
|