add group members

This commit is contained in:
Dietrich 2020-11-19 09:14:00 +01:00
parent 65542c9b69
commit 8b42c8c3b2
Signed by: dietrich
GPG Key ID: 9F3C20C0F85DF67C
4 changed files with 72 additions and 19 deletions

View File

@ -8,6 +8,12 @@ use std::convert::TryFrom;
use std::fmt::{self, Debug, Display};
use std::{cmp::Eq, rc::Rc};
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Membership {
Primary,
Member,
}
#[derive(Debug, PartialEq, Eq)]
pub struct Groupname {
groupname: String,

View File

@ -9,12 +9,6 @@ use log::{debug, error, info, trace, warn};
use std::convert::TryFrom;
use std::fmt::{self, Display};
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum GroupMembership {
Primary,
Member,
}
/// A record(line) in the user database `/etc/passwd` found in most linux systems.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct User {
@ -27,7 +21,7 @@ pub struct User {
gecos: crate::Gecos, /* Real name. */
home_dir: crate::HomeDir, /* Home directory. */
shell_path: crate::ShellPath, /* Shell program. */
groups: Vec<(GroupMembership, crate::Group)>,
groups: Vec<(crate::group::Membership, crate::Group)>,
}
impl User {
@ -73,6 +67,20 @@ impl User {
self.shell_path = crate::ShellPath { shell: path };
self
}
pub fn add_group(
&mut self,
group_type: crate::group::Membership,
group: crate::Group,
) -> &mut Self {
self.groups.push((group_type, group));
self
}
#[must_use]
pub const fn get_groups(&self) -> &Vec<(crate::group::Membership, crate::Group)> {
&self.groups
}
}
impl NewFromString for User {

View File

@ -90,7 +90,7 @@ impl NewFromString for Shadow {
/// ```
/// use umanux::NewFromString;
/// let shad = umanux::Shadow::new_from_string(
/// "test:!!$6$/RotIe4VZzzAun4W$7YUONvru1rDnllN5TvrnOMsWUD5wSDUPAD6t6/Xwsr/0QOuWF3HcfAhypRkGa8G1B9qqWV5kZSnCb8GKMN9N61:18260:0:99999:7:::".to_string(),
/// "test:$6$u0Hh.9WKRF1Aeu4g$XqoDyL6Re/4ZLNQCGAXlNacxCxbdigexEqzFzkOVPV5Z1H23hlenjW8ZLgq6GQtFURYwenIFpo1c.r4aW9l5S/:18260:0:99999:7:::".to_string(),
/// 0,
/// ).unwrap();
/// assert_eq!(shad.get_username(), "test");
@ -152,7 +152,7 @@ fn duration_for_days(days_source: &str) -> Option<chrono::Duration> {
#[test]
fn test_parse_and_back_identity() {
let line = "test:!!$6$/RotIe4VZzzAun4W$7YUONvru1rDnllN5TvrnOMsWUD5wSDUPAD6t6/Xwsr/0QOuWF3HcfAhypRkGa8G1B9qqWV5kZSnCb8GKMN9N61:18260:0:99999:7:::";
let line = "test:$6$u0Hh.9WKRF1Aeu4g$XqoDyL6Re/4ZLNQCGAXlNacxCxbdigexEqzFzkOVPV5Z1H23hlenjW8ZLgq6GQtFURYwenIFpo1c.r4aW9l5S/:18260:0:99999:7:::";
let line2 = Shadow::new_from_string(line.to_owned(), 0).unwrap();
assert_eq!(format!("{}", line2), line);
}

View File

@ -15,10 +15,12 @@ use std::collections::HashMap;
use std::fs::File;
use std::io::{BufReader, Read};
pub type UserList = HashMap<String, crate::User>;
pub struct UserDBLocal {
source_files: files::Files,
source_hashes: hashes::Hashes, // to detect changes
pub users: HashMap<String, crate::User>,
pub users: UserList,
pub groups: Vec<crate::Group>,
}
@ -64,6 +66,7 @@ impl UserDBLocal {
let passwds: Vec<crate::Shadow> = string_to(&my_shadow_lines);
let groups: Vec<crate::Group> = string_to(&my_group_lines);
shadow_to_users(&mut users, passwds);
groups_to_users(&mut users, &groups);
Ok(Self {
source_files: files,
users,
@ -346,11 +349,41 @@ fn file_to_string(file: &File) -> Result<String, crate::UserLibError> {
}
}
fn groups_to_users<'a>(users: &'a mut UserList, groups: &'a [crate::Group]) -> &'a mut UserList {
for group in groups {
match group.get_member_names() {
Some(usernames) => {
for username in usernames {
if let Some(user) = users.get_mut(username) {
user.add_group(crate::group::Membership::Member, group.clone());
}
}
}
None => continue,
}
}
for user in users.values_mut() {
let gid = user.get_gid();
let grouplist: Vec<&crate::Group> = groups
.iter()
.filter(|g| g.get_gid().unwrap() == gid)
.collect();
if grouplist.len() == 1 {
let group = *grouplist.first().unwrap();
user.add_group(crate::group::Membership::Primary, group.clone());
} else {
error!(
"Somehow the group with gid {} was found {} times",
gid,
grouplist.len()
);
}
}
users
}
/// Merge the Shadow passwords into the users
fn shadow_to_users(
users: &mut HashMap<String, crate::User>,
shadow: Vec<crate::Shadow>,
) -> &mut HashMap<String, crate::User> {
fn shadow_to_users(users: &mut UserList, shadow: Vec<crate::Shadow>) -> &mut UserList {
for pass in shadow {
let user = users
.get_mut(pass.get_username())
@ -360,8 +393,8 @@ fn shadow_to_users(
users
}
/// Convert a `Vec<crate::User>` to a `HashMap<String, crate::User>` where the username is used as key
fn user_vec_to_hashmap(users: Vec<crate::User>) -> HashMap<String, crate::User> {
/// Convert a `Vec<crate::User>` to a `UserList` (`HashMap<String, crate::User>`) where the username is used as key
fn user_vec_to_hashmap(users: Vec<crate::User>) -> UserList {
users
.into_iter()
.map(|x| {
@ -413,11 +446,17 @@ where
#[test]
fn test_creator_user_db_local() {
let data = UserDBLocal::import_from_strings("test:x:1001:1001:full Name,004,000342,001-2312,myemail@test.com:/home/test:/bin/test", "test:!!$6$/RotIe4VZzzAun4W$7YUONvru1rDnllN5TvrnOMsWUD5wSDUPAD6t6/Xwsr/0QOuWF3HcfAhypRkGa8G1B9qqWV5kZSnCb8GKMN9N61:18260:0:99999:7:::", "teste:x:1002:test,test");
let data = UserDBLocal::import_from_strings("test:x:1001:1001:full Name,004,000342,001-2312,myemail@test.com:/home/test:/bin/test", "test:$6$u0Hh.9WKRF1Aeu4g$XqoDyL6Re/4ZLNQCGAXlNacxCxbdigexEqzFzkOVPV5Z1H23hlenjW8ZLgq6GQtFURYwenIFpo1c.r4aW9l5S/:18260:0:99999:7:::", "teste:x:1002:test,test");
assert_eq!(
data.users.get("test").unwrap().get_username().unwrap(),
"test"
)
);
for user in data.users.values() {
if let Some((member, group)) = user.get_groups().first() {
assert_eq!(*member, crate::group::Membership::Member);
assert_eq!(group.get_groupname(), Some("teste"));
}
}
}
#[test]
@ -465,7 +504,7 @@ fn test_user_db_read_implementation() {
#[test]
fn test_user_db_write_implementation() {
use crate::api::DeleteUserArgs;
let mut data = UserDBLocal::import_from_strings("test:x:1001:1001:full Name,004,000342,001-2312,myemail@test.com:/home/test:/bin/test", "test:!!$6$/RotIe4VZzzAun4W$7YUONvru1rDnllN5TvrnOMsWUD5wSDUPAD6t6/Xwsr/0QOuWF3HcfAhypRkGa8G1B9qqWV5kZSnCb8GKMN9N61:18260:0:99999:7:::", "teste:x:1002:test,test");
let mut data = UserDBLocal::import_from_strings("test:x:1001:1001:full Name,004,000342,001-2312,myemail@test.com:/home/test:/bin/test", "test:$6$u0Hh.9WKRF1Aeu4g$XqoDyL6Re/4ZLNQCGAXlNacxCxbdigexEqzFzkOVPV5Z1H23hlenjW8ZLgq6GQtFURYwenIFpo1c.r4aW9l5S/:18260:0:99999:7:::", "teste:x:1002:test,test");
let user = "test";
assert_eq!(data.get_all_users().len(), 1);