IMAPServer_shared/config/
mod.rs

1use log::error;
2use rand::distributions::Alphanumeric;
3use rand::prelude::*;
4use serde::{Deserialize, Serialize};
5use tokio::fs::metadata;
6use tokio::fs::File;
7use tokio::io::{AsyncReadExt, AsyncWriteExt};
8
9#[derive(Debug, PartialEq, Serialize, Deserialize)]
10pub struct Config {
11    pub shared_secret: String,
12    pub mailbox_root: String,
13}
14
15impl Config {
16    pub async fn new() -> Option<Self> {
17        let mut rng = StdRng::from_entropy();
18        // This does need to stay mutable even when the compiler says otherwise. If it is not mut it fails to generate random numbers
19        #[allow(unused_mut)]
20        let mut random_string: String;
21
22        if rng.gen() {
23            random_string = rng.sample_iter(&Alphanumeric).take(100).collect::<String>();
24        } else {
25            return None;
26        }
27
28        let config = Self {
29            shared_secret: random_string,
30            mailbox_root: "./mailbox_root".to_string(),
31        };
32
33        // TODO consider using /etc/ImapServer/Config.yml instead
34        let c = serde_yaml::to_string(&config).expect("unable to convert config to string");
35        let mut file = File::create("./Config.yml")
36            .await
37            .expect("unable to create file");
38        let wrote = file.write_all(c.as_bytes()).await;
39
40        match wrote {
41            Ok(_) => {
42                return Some(config);
43            }
44            Err(e) => {
45                error!("{}", e);
46                return None;
47            }
48        }
49    }
50
51    pub async fn load() -> Option<Self> {
52        let metadata = metadata("./Config.yml").await;
53        match metadata {
54            Ok(metadata) => {
55                if metadata.is_file() {
56                    let mut file = File::open("./Config.yml")
57                        .await
58                        .expect("unable to open file");
59                    let mut data = String::new();
60                    file.read_to_string(&mut data)
61                        .await
62                        .expect("unable to read config file");
63
64                    let deserialized_config: Self = serde_yaml::from_str(&data)
65                        .expect("unable to make struct from config content");
66
67                    return Some(deserialized_config);
68                } else {
69                    return Config::new().await;
70                }
71            }
72
73            Err(e) => {
74                error!("{}", e);
75                return Config::new().await;
76            }
77        }
78    }
79}