tetratto/crates/tetratto_core/src/config.rs

200 lines
5 KiB
Rust
Raw Normal View History

2025-03-21 01:38:07 -04:00
use pathbufd::PathBufD;
use serde::{Deserialize, Serialize};
use std::fs;
use std::io::Result;
/// Security configuration.
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct SecurityConfig {
/// If registrations are enabled.
#[serde(default = "default_security_registration_enabled")]
pub registration_enabled: bool,
/// If registrations are enabled.
#[serde(default = "default_security_admin_user")]
pub admin_user: String,
/// If registrations are enabled.
#[serde(default = "default_real_ip_header")]
pub real_ip_header: String,
2025-03-21 01:38:07 -04:00
}
fn default_security_registration_enabled() -> bool {
true
}
fn default_security_admin_user() -> String {
"admin".to_string()
}
fn default_real_ip_header() -> String {
"CF-Connecting-IP".to_string()
}
2025-03-21 01:38:07 -04:00
impl Default for SecurityConfig {
fn default() -> Self {
Self {
registration_enabled: default_security_registration_enabled(),
admin_user: default_security_admin_user(),
real_ip_header: default_real_ip_header(),
2025-03-21 01:38:07 -04:00
}
}
}
/// Directories configuration.
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct DirsConfig {
/// HTML templates directory.
#[serde(default = "default_dir_templates")]
pub templates: String,
/// Static files directory.
#[serde(default = "default_dir_assets")]
pub assets: String,
/// Media (user avatars/banners) files directory.
#[serde(default = "default_dir_media")]
pub media: String,
2025-03-21 01:38:07 -04:00
}
fn default_dir_templates() -> String {
"html".to_string()
}
fn default_dir_assets() -> String {
"public".to_string()
}
fn default_dir_media() -> String {
"media".to_string()
}
2025-03-21 01:38:07 -04:00
impl Default for DirsConfig {
fn default() -> Self {
Self {
templates: default_dir_templates(),
assets: default_dir_assets(),
media: default_dir_media(),
}
}
}
/// Database configuration.
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct DatabaseConfig {
pub name: String,
#[cfg(feature = "postgres")]
pub url: String,
#[cfg(feature = "postgres")]
pub user: String,
#[cfg(feature = "postgres")]
pub password: String,
}
impl Default for DatabaseConfig {
fn default() -> Self {
Self {
name: "atto.db".to_string(),
#[cfg(feature = "postgres")]
url: "localhost:5432".to_string(),
#[cfg(feature = "postgres")]
user: "postgres".to_string(),
#[cfg(feature = "postgres")]
password: "postgres".to_string(),
2025-03-21 01:38:07 -04:00
}
}
}
/// Configuration file
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct Config {
/// The name of the app.
2025-03-21 01:38:07 -04:00
#[serde(default = "default_name")]
pub name: String,
/// The description of the app.
#[serde(default = "default_description")]
pub description: String,
/// The theme color of the app.
#[serde(default = "default_color")]
pub color: String,
2025-03-21 01:38:07 -04:00
/// The port to serve the server on.
#[serde(default = "default_port")]
pub port: u16,
/// Database security.
#[serde(default = "default_security")]
pub security: SecurityConfig,
/// The locations where different files should be matched.
#[serde(default = "default_dirs")]
pub dirs: DirsConfig,
#[serde(default = "default_database")]
pub database: DatabaseConfig,
2025-03-21 01:38:07 -04:00
}
fn default_name() -> String {
"Tetratto".to_string()
}
fn default_description() -> String {
"🐐 tetratto!".to_string()
2025-03-21 01:38:07 -04:00
}
fn default_color() -> String {
"#c9b1bc".to_string()
}
fn default_port() -> u16 {
4118
2025-03-21 01:38:07 -04:00
}
fn default_security() -> SecurityConfig {
SecurityConfig::default()
}
fn default_dirs() -> DirsConfig {
DirsConfig::default()
}
fn default_database() -> DatabaseConfig {
DatabaseConfig::default()
}
2025-03-21 01:38:07 -04:00
impl Default for Config {
fn default() -> Self {
Self {
name: default_name(),
description: default_description(),
color: default_color(),
2025-03-21 01:38:07 -04:00
port: default_port(),
database: default_database(),
security: default_security(),
dirs: default_dirs(),
}
}
}
impl Config {
/// Read configuration file into [`Config`]
pub fn read(contents: String) -> Self {
toml::from_str::<Self>(&contents).unwrap()
}
/// Pull configuration file
pub fn get_config() -> Self {
let path = PathBufD::current().join("tetratto.toml");
match fs::read_to_string(&path) {
Ok(c) => Config::read(c),
Err(_) => {
Self::update_config(Self::default()).expect("failed to write default config");
Self::default()
}
}
}
/// Update configuration file
pub fn update_config(contents: Self) -> Result<()> {
let c = fs::canonicalize(".").unwrap();
let here = c.to_str().unwrap();
fs::write(
format!("{here}/tetratto.toml"),
toml::to_string_pretty::<Self>(&contents).unwrap(),
)
}
}