use figment::{Figment, providers::Serialized};
use std::path::PathBuf;
#[cfg(feature = "client")]
mod client;
#[allow(clippy::module_inception)]
mod config;
#[cfg(feature = "tools-grypedb")]
mod grypedb;
#[cfg(feature = "models")]
mod models;
mod server;
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct Config {
#[serde(skip)]
path: PathBuf,
#[serde(skip)]
data_path: PathBuf,
#[serde(default)]
pub database: DatabaseConfig,
#[serde(default)]
pub server: ServerConfig,
#[serde(default)]
pub agent: AgentConfig,
#[serde(default)]
pub sessions: SessionsConfig,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct DatabaseConfig {
#[serde(skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
pub token: Option<String>,
}
impl DatabaseConfig {
pub(crate) fn figment(base: &Self) -> Figment {
Figment::from(Serialized::defaults(base))
.merge(figment::providers::Env::prefixed("KONARR_DB_"))
}
}
impl Default for DatabaseConfig {
fn default() -> Self {
let path = if let Ok(p) = std::env::var("KONARR_DB_PATH") {
Some(p)
} else if let Ok(data_path) = std::env::var("KONARR_DATA_PATH") {
let path = PathBuf::from(data_path).join("konarr.db");
Some(path.to_string_lossy().to_string())
} else {
None
};
Self { path, token: None }
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ServerConfig {
#[serde(default)]
pub secret: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub domain: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub port: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub scheme: Option<String>,
#[serde(default)]
pub cors: bool,
#[serde(default)]
pub frontend: PathBuf,
#[serde(skip_serializing_if = "Option::is_none")]
pub api: Option<String>,
}
impl Default for ServerConfig {
fn default() -> Self {
let frontend = match std::env::var("KONARR_CLIENT_PATH") {
Ok(path) => PathBuf::from(path),
Err(_) => PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("frontend")
.join("build"),
};
Self {
secret: String::new(),
domain: None,
port: None,
scheme: None,
cors: true,
frontend,
api: Some("/api".to_string()),
}
}
}
impl ServerConfig {
pub(crate) fn figment(base: &Self) -> Figment {
Figment::from(Serialized::defaults(Self::default()))
.merge(Serialized::defaults(base))
.merge(figment::providers::Env::prefixed("KONARR_SERVER_"))
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct SessionsConfig {
pub admins: SessionsRoleConfig,
pub users: SessionsRoleConfig,
pub agents: SessionsRoleConfig,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct SessionsRoleConfig {
pub expires: i32,
}
impl Default for SessionsConfig {
fn default() -> Self {
Self {
admins: SessionsRoleConfig { expires: 1 },
users: SessionsRoleConfig { expires: 24 },
agents: SessionsRoleConfig { expires: 720 },
}
}
}
#[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct AgentConfig {
#[serde(rename = "project-id", skip_serializing_if = "Option::is_none")]
pub project_id: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub host: Option<String>,
#[serde(default)]
pub create: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub token: Option<String>,
#[serde(default)]
pub monitoring: bool,
#[serde(rename = "docker-socket", skip_serializing_if = "Option::is_none")]
pub docker_socket: Option<String>,
pub tool: Option<String>,
#[serde(default)]
pub tool_auto_install: bool,
#[serde(default)]
pub tool_auto_update: bool,
}
impl AgentConfig {
pub(crate) fn figment(base: &Self) -> Figment {
Figment::from(Serialized::defaults(base))
.merge(figment::providers::Env::prefixed("KONARR_AGENT_"))
}
}