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
130
131
132
133
134
135
136
137
138
139
140
|
use std::{
fs,
io::{Error, ErrorKind},
path::PathBuf,
};
use cfg_file::config::ConfigFile;
use crate::{
constants::{SERVER_FILE_MEMBER_INFO, SERVER_FILE_MEMBER_PUB, SERVER_PATH_MEMBERS},
data::{
member::Member,
vault::{MemberId, Vault},
},
};
const ID_PARAM: &str = "{member_id}";
/// Member Manage
impl Vault {
/// Read member from configuration file
pub async fn member(&self, id: &MemberId) -> Result<Member, std::io::Error> {
if let Some(cfg_file) = self.member_cfg(id) {
let member = Member::read_from(cfg_file).await?;
return Ok(member);
}
Err(Error::new(ErrorKind::NotFound, "Member not found!"))
}
/// List all member IDs in the vault
pub fn member_ids(&self) -> Result<Vec<MemberId>, std::io::Error> {
let members_path = self.vault_path.join(SERVER_PATH_MEMBERS);
if !members_path.exists() {
return Ok(Vec::new());
}
let mut member_ids = Vec::new();
for entry in fs::read_dir(members_path)? {
let entry = entry?;
let path = entry.path();
if path.is_file()
&& let Some(file_name) = path.file_stem().and_then(|s| s.to_str())
&& path.extension().and_then(|s| s.to_str()) == Some("toml")
{
member_ids.push(file_name.to_string());
}
}
Ok(member_ids)
}
/// Get all members
/// This method will read and deserialize member information, please pay attention to performance issues
pub async fn members(&self) -> Result<Vec<Member>, std::io::Error> {
let mut members = Vec::new();
for member_id in self.member_ids()? {
if let Ok(member) = self.member(&member_id).await {
members.push(member);
}
}
Ok(members)
}
/// Update member info
pub async fn update_member(&self, member: Member) -> Result<(), std::io::Error> {
// Ensure member exist
if self.member_cfg(&member.id()).is_some() {
let member_cfg_path = self.member_cfg_path(&member.id());
Member::write_to(&member, member_cfg_path).await?;
return Ok(());
}
Err(Error::new(ErrorKind::NotFound, "Member not found!"))
}
/// Register a member to vault
pub async fn register_member_to_vault(&self, member: Member) -> Result<(), std::io::Error> {
// Ensure member not exist
if self.member_cfg(&member.id()).is_some() {
return Err(Error::new(
ErrorKind::DirectoryNotEmpty,
format!("Member `{}` already registered!", member.id()),
));
}
// Wrtie config file to member dir
let member_cfg_path = self.member_cfg_path(&member.id());
Member::write_to(&member, member_cfg_path).await?;
Ok(())
}
/// Remove member from vault
pub fn remove_member_from_vault(&self, id: &MemberId) -> Result<(), std::io::Error> {
// Ensure member exist
if let Some(member_cfg_path) = self.member_cfg(id) {
fs::remove_file(member_cfg_path)?;
}
Ok(())
}
/// Try to get the member's configuration file to determine if the member exists
pub fn member_cfg(&self, id: &MemberId) -> Option<PathBuf> {
let cfg_file = self.member_cfg_path(id);
if cfg_file.exists() {
Some(cfg_file)
} else {
None
}
}
/// Try to get the member's public key file to determine if the member has login permission
pub fn member_key(&self, id: &MemberId) -> Option<PathBuf> {
let key_file = self.member_key_path(id);
if key_file.exists() {
Some(key_file)
} else {
None
}
}
/// Get the member's configuration file path, but do not check if the file exists
pub fn member_cfg_path(&self, id: &MemberId) -> PathBuf {
self.vault_path
.join(SERVER_FILE_MEMBER_INFO.replace(ID_PARAM, id.to_string().as_str()))
}
/// Get the member's public key file path, but do not check if the file exists
pub fn member_key_path(&self, id: &MemberId) -> PathBuf {
self.vault_path
.join(SERVER_FILE_MEMBER_PUB.replace(ID_PARAM, id.to_string().as_str()))
}
}
|