1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use std::{
io::{Read, Write},
os::unix::fs::PermissionsExt,
path::{Path, PathBuf},
};
use chrono::prelude::*;
use super::errors::*;
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "type", content = "value")]
pub enum SendMail {
Smtp(melib::smtp::SmtpServerConf),
ShellCommand(String),
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Configuration {
pub send_mail: SendMail,
pub db_path: PathBuf,
pub data_path: PathBuf,
#[serde(default)]
pub administrators: Vec<String>,
}
impl Configuration {
pub fn new(db_path: impl Into<PathBuf>) -> Self {
let db_path = db_path.into();
Self {
send_mail: SendMail::ShellCommand("/usr/bin/false".to_string()),
data_path: db_path
.parent()
.map(Path::to_path_buf)
.unwrap_or_else(|| db_path.clone()),
administrators: vec![],
db_path,
}
}
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self> {
let path = path.as_ref();
let mut s = String::new();
let mut file = std::fs::File::open(path)?;
file.read_to_string(&mut s)?;
let config: Self = toml::from_str(&s).context(format!(
"Could not parse configuration file `{}` succesfully: ",
path.display()
))?;
Ok(config)
}
pub fn data_directory(&self) -> &Path {
self.data_path.as_path()
}
pub fn db_path(&self) -> &Path {
self.db_path.as_path()
}
pub fn save_message_to_path(&self, msg: &str, mut path: PathBuf) -> Result<PathBuf> {
if path.is_dir() {
let now = Local::now().timestamp();
path.push(format!("{}-failed.eml", now));
}
debug_assert!(path != self.db_path());
let mut file = std::fs::File::create(&path)?;
let metadata = file.metadata()?;
let mut permissions = metadata.permissions();
permissions.set_mode(0o600); file.set_permissions(permissions)?;
file.write_all(msg.as_bytes())?;
file.flush()?;
Ok(path)
}
pub fn save_message(&self, msg: String) -> Result<PathBuf> {
self.save_message_to_path(&msg, self.data_directory().to_path_buf())
}
pub fn to_toml(&self) -> String {
toml::Value::try_from(self)
.expect("Could not serialize config to TOML")
.to_string()
}
}