posemesh_node_registration/
persist.rs1use anyhow::{anyhow, Result};
2use std::collections::HashMap;
3use std::path::{Path, PathBuf};
4use std::sync::{Mutex, MutexGuard, OnceLock};
5
6pub const NODE_SECRET_PATH: &str = "data/node_secret";
7static NODE_SECRET_STORE: OnceLock<Mutex<HashMap<PathBuf, String>>> = OnceLock::new();
8
9fn node_secret_store() -> &'static Mutex<HashMap<PathBuf, String>> {
10 NODE_SECRET_STORE.get_or_init(|| Mutex::new(HashMap::new()))
11}
12
13fn lock_node_secret_store() -> Result<MutexGuard<'static, HashMap<PathBuf, String>>> {
14 node_secret_store()
15 .lock()
16 .map_err(|_| anyhow!("node secret store poisoned"))
17}
18
19pub fn write_node_secret_to_path(path: &Path, secret: &str) -> Result<()> {
21 let mut store = lock_node_secret_store()?;
22 store.insert(path.to_path_buf(), secret.to_owned());
23 Ok(())
24}
25
26pub fn read_node_secret_from_path(path: &Path) -> Result<Option<String>> {
28 let store = lock_node_secret_store()?;
29 Ok(store.get(path).cloned())
30}
31
32pub fn write_node_secret(secret: &str) -> Result<()> {
34 write_node_secret_to_path(Path::new(NODE_SECRET_PATH), secret)
35}
36
37pub fn read_node_secret() -> Result<Option<String>> {
39 read_node_secret_from_path(Path::new(NODE_SECRET_PATH))
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45
46 #[test]
47 fn write_and_read_roundtrip() {
48 let path = PathBuf::from(format!("node_secret_{}", uuid::Uuid::new_v4()));
49
50 write_node_secret_to_path(&path, "first").unwrap();
51 let got = read_node_secret_from_path(&path).unwrap();
52 assert_eq!(got.as_deref(), Some("first"));
53
54 write_node_secret_to_path(&path, "second").unwrap();
55 let got2 = read_node_secret_from_path(&path).unwrap();
56 assert_eq!(got2.as_deref(), Some("second"));
57
58 let other_path = PathBuf::from(format!("node_secret_other_{}", uuid::Uuid::new_v4()));
59 assert!(read_node_secret_from_path(&other_path).unwrap().is_none());
60
61 let mut store = lock_node_secret_store().unwrap();
62 store.remove(&path);
63 store.remove(&other_path);
64 }
65}