implement UserDbRead

This commit is contained in:
Dietrich 2020-10-18 15:22:17 +02:00
parent 60bbe1ef1b
commit 403f948c67
4 changed files with 89 additions and 28 deletions

View File

@ -1,27 +1,27 @@
trait UserDBRead { pub trait UserDBRead {
fn get_all_users(&self) -> Vec<crate::User>; fn get_all_users(&self) -> Vec<&crate::User>;
fn get_user_by_name(&self, name: &str) -> Option<crate::User>; fn get_user_by_name(&self, name: &str) -> Option<&crate::User>;
fn get_user_by_id(&self, uid: u64) -> Option<crate::User>; fn get_user_by_id(&self, uid: u32) -> Option<&crate::User>;
fn get_all_groups(&self) -> Vec<crate::Group>; fn get_all_groups(&self) -> Vec<&crate::Group>;
fn get_group_by_name(&self) -> Option<crate::Group>; fn get_group_by_name(&self, name: &str) -> Option<&crate::Group>;
fn get_group_by_id(&self) -> Option<crate::Group>; fn get_group_by_id(&self, name: u32) -> Option<&crate::Group>;
} }
trait UserDBValidation { pub trait UserDBValidation {
fn is_uid_valid_and_free(&self) -> bool; fn is_uid_valid_and_free(&self) -> bool;
fn is_username_valid_and_free(&self) -> bool; fn is_username_valid_and_free(&self) -> bool;
fn is_gid_valid_and_free(&self) -> bool; fn is_gid_valid_and_free(&self) -> bool;
fn is_groupname_valid_and_free(&self) -> bool; fn is_groupname_valid_and_free(&self) -> bool;
} }
trait UserDBWrite { pub trait UserDBWrite {
fn delete_user(&self) -> Option<crate::User>; fn delete_user(&self) -> Option<crate::User>;
fn new_user(&self) -> Option<crate::User>; fn new_user(&self) -> Option<crate::User>;
fn delete_group(&self) -> Option<crate::Group>; fn delete_group(&self) -> Option<crate::Group>;
fn new_group(&self) -> Option<crate::Group>; fn new_group(&self) -> Option<crate::Group>;
} }
trait UserRead { pub trait UserRead {
fn get_username(&self) -> Option<crate::User>; fn get_username(&self) -> Option<crate::User>;
fn get_uid(&self) -> Option<crate::User>; fn get_uid(&self) -> Option<crate::User>;
fn get_gid(&self) -> Option<crate::User>; fn get_gid(&self) -> Option<crate::User>;
@ -36,7 +36,7 @@ trait UserRead {
fn get_other(&self) -> Option<Vec<String>>; fn get_other(&self) -> Option<Vec<String>>;
} }
trait UserWrite { pub trait UserWrite {
fn set_username(&self) -> Option<crate::User>; fn set_username(&self) -> Option<crate::User>;
fn set_uid(&self) -> Option<crate::User>; fn set_uid(&self) -> Option<crate::User>;
fn set_gid(&self) -> Option<crate::User>; fn set_gid(&self) -> Option<crate::User>;
@ -51,14 +51,14 @@ trait UserWrite {
fn set_other(&self) -> Option<Vec<String>>; fn set_other(&self) -> Option<Vec<String>>;
} }
trait GroupRead { pub trait GroupRead {
fn get_groupname(&self) -> Option<crate::Group>; fn get_groupname(&self) -> Option<crate::Group>;
fn get_encrypted_password(&self) -> Option<crate::Group>; fn get_encrypted_password(&self) -> Option<crate::Group>;
fn get_gid(&self) -> Option<crate::Group>; fn get_gid(&self) -> Option<crate::Group>;
fn get_members(&self) -> Option<crate::Group>; fn get_members(&self) -> Option<crate::Group>;
} }
trait GroupWrite<T> { pub trait GroupWrite<T> {
fn set_groupname(&self) -> Option<crate::Group>; fn set_groupname(&self) -> Option<crate::Group>;
fn set_password(&self) -> Option<crate::Group>; fn set_password(&self) -> Option<crate::Group>;
fn set_gid(&self) -> Option<crate::Group>; fn set_gid(&self) -> Option<crate::Group>;

View File

@ -66,6 +66,10 @@ impl Group {
pub const fn get_members(&self) -> &Vec<crate::Username> { pub const fn get_members(&self) -> &Vec<crate::Username> {
&self.members &self.members
} }
pub fn get_gid(&self) -> u32 {
self.gid.get_gid()
}
} }
impl Display for Group { impl Display for Group {

View File

@ -147,6 +147,10 @@ impl Gid {
// since it is a u32 it cannot be smaller than 0 // since it is a u32 it cannot be smaller than 0
self.gid < 1000 self.gid < 1000
} }
pub const fn get_gid(&self) -> u32 {
self.gid
}
} }
/// The home directory of a user /// The home directory of a user

View File

@ -16,7 +16,7 @@ use std::path::PathBuf;
pub struct UserDBLocal { pub struct UserDBLocal {
source_files: Files, source_files: Files,
pub users: HashMap<String, crate::User>, pub users: HashMap<String, crate::User>,
pub group_entries: Vec<crate::Group>, pub groups: Vec<crate::Group>,
} }
pub struct Files { pub struct Files {
@ -55,7 +55,7 @@ impl UserDBLocal {
shadow: None, shadow: None,
}, },
users, users,
group_entries: groups, groups,
}; };
res res
} }
@ -73,10 +73,52 @@ impl UserDBLocal {
Self { Self {
source_files: files, source_files: files,
users, users,
group_entries: string_to(&my_group_lines), groups: string_to(&my_group_lines),
} }
} }
} }
use crate::api::UserDBRead;
impl UserDBRead for UserDBLocal {
fn get_all_users(&self) -> Vec<&crate::User> {
self.users.iter().map(|(_, x)| x).collect()
}
fn get_user_by_name(&self, name: &str) -> Option<&crate::User> {
self.users.get(name)
}
fn get_user_by_id(&self, uid: u32) -> Option<&crate::User> {
// could probably be more efficient - on the other hand its no problem to loop a thousand users.
for (_, user) in self.users.iter() {
if user.get_uid() == uid {
return Some(&user);
}
}
None
}
fn get_all_groups(&self) -> Vec<&crate::Group> {
self.groups.iter().collect()
}
fn get_group_by_name(&self, name: &str) -> Option<&crate::Group> {
for group in self.groups.iter() {
if group.get_groupname() == name {
return Some(group);
}
}
None
}
fn get_group_by_id(&self, id: u32) -> Option<&crate::Group> {
for group in self.groups.iter() {
if group.get_gid() == id {
return Some(group);
}
}
None
}
}
/// Parse a file to a string /// Parse a file to a string
fn file_to_string(path: Option<&PathBuf>) -> String { fn file_to_string(path: Option<&PathBuf>) -> String {
@ -129,7 +171,7 @@ where
.lines() .lines()
.filter_map(|line| { .filter_map(|line| {
if line.len() > 5 { if line.len() > 5 {
println!("{}", line); //println!("{}", line);
Some(T::new_from_string(line.to_owned()).expect("failed to read lines")) Some(T::new_from_string(line.to_owned()).expect("failed to read lines"))
} else { } else {
None None
@ -146,16 +188,27 @@ fn test_creator_user_db_local() {
#[test] #[test]
fn test_parsing_local_database() { fn test_parsing_local_database() {
use std::fs::File; // Parse the worldreadable user database ignore the shadow database as this would require root privileges.
use std::io::{BufReader, Read}; let my_passwd_lines = file_to_string(Some(&PathBuf::from("/etc/passwd")));
let passwd_file = File::open("/etc/passwd").unwrap(); let my_group_lines = file_to_string(Some(&PathBuf::from("/etc/group")));
let mut passwd_reader = BufReader::new(passwd_file);
let mut my_passwd_lines = "".to_string();
passwd_reader.read_to_string(&mut my_passwd_lines).unwrap();
let group_file = File::open("/etc/group").unwrap();
let mut group_reader = BufReader::new(group_file);
let mut my_group_lines = "".to_string();
group_reader.read_to_string(&mut my_group_lines).unwrap();
let data = UserDBLocal::import_from_strings(&my_passwd_lines, "", &my_group_lines); let data = UserDBLocal::import_from_strings(&my_passwd_lines, "", &my_group_lines);
assert_eq!(data.group_entries.get(0).unwrap().get_groupname(), "root"); assert_eq!(data.groups.get(0).unwrap().get_groupname(), "root");
}
#[test]
fn test_user_db_read_implementation() {
let pass = file_to_string(Some(&PathBuf::from("/etc/passwd")));
let group = file_to_string(Some(&PathBuf::from("/etc/group")));
let data = UserDBLocal::import_from_strings(&pass, "", &group);
// Usually there are more than 10 users
assert!(data.get_all_users().len() > 10);
assert!(data.get_user_by_name("root").is_some());
assert_eq!(data.get_user_by_name("root").unwrap().get_uid(), 0);
assert_eq!(data.get_user_by_id(0).unwrap().get_username(), "root");
assert!(data.get_all_groups().len() > 10);
assert!(data.get_group_by_name("root").is_some());
assert_eq!(data.get_group_by_name("root").unwrap().get_gid(), 0);
assert_eq!(data.get_group_by_id(0).unwrap().get_groupname(), "root");
assert!(data.get_user_by_name("norealnameforsure").is_none());
assert!(data.get_group_by_name("norealgroupforsure").is_none());
} }