use toml_edit::
{
Item,
Table,
Value,
};
use crate::
{
consts,
role::Role,
};
fn set_user_field(users: &mut Table, username: &str, key: &str, value: Value) {
if users.get(username).and_then(Item::as_table_like).is_none()
{
users.insert(username, Item::Table(Table::new()));
}
users.get_mut(username).and_then(Item::as_table_like_mut)
.expect("User entry is not a table").insert(key, Item::Value(value));
}
fn write_user_field(username: &str, key: &str, value: Value) {
super::with_cached_mut(&super::config_path(consts::SERVER_USERS_CONFIG), |doc| set_user_field(doc.as_table_mut(), username, key, value));
}
pub fn len() -> usize {
super::get_data(&super::config_path(consts::SERVER_USERS_CONFIG)).len()
}
pub fn password(username: &str) -> Option<String> {
super::get_data(&super::config_path(consts::SERVER_USERS_CONFIG)).get(username)?
.as_table_like()?.get("password")?.as_str().map(str::to_string)
}
pub fn role(username: &str) -> Option<Role> {
super::get_data(&super::config_path(consts::SERVER_USERS_CONFIG)).get(username)?
.as_table_like()?.get("role")?.as_str()?.parse().ok()
}
pub fn set_role(username: &str, role: Role) {
write_user_field(username, "role", role.name().into());
}
pub fn add(username: &str, hash: &str) -> bool {
let first_user = len() == 0;
write_user_field(username, "password", hash.into()); set_role(username, if first_user { Role::Owner } else { Role::User });
first_user
}
pub fn migrate() {
let path = super::config_path(consts::SERVER_USERS_CONFIG);
let legacy: Vec<(String, String)> = super::get_data(&path).as_table().iter()
.filter_map(|(username, item)| match item
{
Item::Value(Value::String(hash)) => Some((username.to_string(), hash.value().to_string())),
_ => None
}).collect();
if legacy.is_empty() { return; }
super::with_cached_mut(&path, |doc|
{
for (username, hash) in &legacy
{
set_user_field(doc.as_table_mut(), username, "password", hash.into());
set_user_field(doc.as_table_mut(), username, "role", Role::User.name().into());
}
});
}
pub fn contains(key: &str) -> bool {
super::get_data(&super::config_path(consts::SERVER_USERS_CONFIG)).get(key).is_some()
}