1use std::path::{Path, PathBuf};
4
5use serde::Deserialize;
6
7use crate::ServerError;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
10#[serde(rename_all = "lowercase")]
11pub enum SignupPolicy {
12 Open,
13 Token,
14 Closed,
15}
16
17#[derive(Debug, Clone, PartialEq, Deserialize)]
18#[serde(default, deny_unknown_fields)]
19pub struct ServerConfig {
20 pub listen_addr: String,
22 pub data_dir: PathBuf,
24 pub signup_policy: SignupPolicy,
26 pub signup_token: Option<String>,
29 pub max_tenants_per_key: u32,
31 pub max_tenants: u32,
33}
34
35impl Default for ServerConfig {
36 fn default() -> Self {
37 Self {
38 listen_addr: "0.0.0.0:2222".into(),
39 data_dir: default_data_dir(),
40 signup_policy: SignupPolicy::Token,
41 signup_token: None,
42 max_tenants_per_key: 5,
43 max_tenants: 0,
44 }
45 }
46}
47
48impl ServerConfig {
49 pub fn parse(text: &str) -> Result<Self, ServerError> {
50 Ok(toml::from_str(text)?)
51 }
52
53 pub fn load(path: &Path) -> Result<Self, ServerError> {
54 Self::parse(&std::fs::read_to_string(path)?)
55 }
56}
57
58fn default_data_dir() -> PathBuf {
62 match std::env::var("XDG_DATA_HOME") {
63 Ok(v) if !v.is_empty() => PathBuf::from(v).join("cliband"),
64 _ => {
65 let home = std::env::var("HOME").unwrap_or_else(|_| "/".into());
66 PathBuf::from(home)
67 .join(".local")
68 .join("share")
69 .join("cliband")
70 }
71 }
72}