make Group a Rc<Inner> type

This commit is contained in:
Dietrich 2020-11-17 07:53:49 +01:00
parent 98b1634924
commit 65542c9b69
Signed by: dietrich
GPG Key ID: 9F3C20C0F85DF67C
4 changed files with 24 additions and 13 deletions

View File

@ -7,7 +7,7 @@ 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: u32) -> 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, name: &str) -> Option<&crate::Group>; fn get_group_by_name(&self, name: &str) -> Option<&crate::Group>;
fn get_group_by_id(&self, name: u32) -> Option<&crate::Group>; fn get_group_by_id(&self, name: u32) -> Option<&crate::Group>;
} }

View File

@ -4,9 +4,9 @@ use crate::userlib::NewFromString;
use log::warn; use log::warn;
use crate::UserLibError; use crate::UserLibError;
use std::cmp::Eq;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fmt::{self, Debug, Display}; use std::fmt::{self, Debug, Display};
use std::{cmp::Eq, rc::Rc};
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct Groupname { pub struct Groupname {
@ -38,9 +38,10 @@ pub(crate) fn is_groupname_valid(name: &str) -> bool {
crate::user::passwd_fields::is_username_valid(name) crate::user::passwd_fields::is_username_valid(name)
} }
pub type Group = Rc<Inner>;
/// A record(line) in the user database `/etc/shadow` found in most linux systems. /// A record(line) in the user database `/etc/shadow` found in most linux systems.
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct Group { pub struct Inner {
pos: u32, pos: u32,
source: String, source: String,
groupname: Groupname, /* Username. */ groupname: Groupname, /* Username. */
@ -49,7 +50,7 @@ pub struct Group {
members: Vec<crate::Username>, /* Real name. */ members: Vec<crate::Username>, /* Real name. */
} }
impl Group { impl Inner {
#[must_use] #[must_use]
pub fn remove_in(&self, content: &str) -> String { pub fn remove_in(&self, content: &str) -> String {
content content
@ -61,7 +62,7 @@ impl Group {
} }
use crate::api::GroupRead; use crate::api::GroupRead;
impl GroupRead for Group { impl GroupRead for Inner {
#[must_use] #[must_use]
fn get_groupname(&self) -> Option<&str> { fn get_groupname(&self) -> Option<&str> {
Some(&self.groupname.groupname) Some(&self.groupname.groupname)
@ -84,7 +85,7 @@ impl GroupRead for Group {
} }
} }
impl Display for Group { impl Display for Inner {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!( write!(
f, f,
@ -101,7 +102,7 @@ impl Display for Group {
} }
} }
impl NewFromString for Group { impl NewFromString for Rc<Inner> {
/// Parse a line formatted like one in `/etc/group` and construct a matching [`Group`] instance /// Parse a line formatted like one in `/etc/group` and construct a matching [`Group`] instance
/// ///
/// # Example /// # Example
@ -120,14 +121,14 @@ impl NewFromString for Group {
fn new_from_string(line: String, position: u32) -> Result<Self, UserLibError> { fn new_from_string(line: String, position: u32) -> Result<Self, UserLibError> {
let elements: Vec<String> = line.split(':').map(ToString::to_string).collect(); let elements: Vec<String> = line.split(':').map(ToString::to_string).collect();
if elements.len() == 4 { if elements.len() == 4 {
Ok(Self { Ok(Self::new(Inner {
pos: position, pos: position,
source: line, source: line,
groupname: Groupname::try_from(elements.get(0).unwrap().to_string())?, groupname: Groupname::try_from(elements.get(0).unwrap().to_string())?,
password: crate::Password::Disabled, password: crate::Password::Disabled,
gid: crate::Gid::try_from(elements.get(2).unwrap().to_string())?, gid: crate::Gid::try_from(elements.get(2).unwrap().to_string())?,
members: parse_members_list(elements.get(3).unwrap()), members: parse_members_list(elements.get(3).unwrap()),
}) }))
} else { } else {
Err(format!( Err(format!(
"Failed to parse: not enough elements ({}): {:?}", "Failed to parse: not enough elements ({}): {:?}",
@ -156,7 +157,7 @@ fn parse_members_list(source: &str) -> Vec<crate::Username> {
#[test] #[test]
fn test_parse_and_back_identity() { fn test_parse_and_back_identity() {
let line = "teste:x:1002:test,teste"; let line = "teste:x:1002:test,teste";
let line2 = Group::new_from_string(line.to_owned(), 0).unwrap(); let line2: Group = Group::new_from_string(line.to_owned(), 0).unwrap();
assert_eq!(format!("{}", line2), line); assert_eq!(format!("{}", line2), line);
} }

View File

@ -9,6 +9,12 @@ use log::{debug, error, info, trace, warn};
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fmt::{self, Display}; 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. /// A record(line) in the user database `/etc/passwd` found in most linux systems.
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub struct User { pub struct User {
@ -21,6 +27,7 @@ pub struct User {
gecos: crate::Gecos, /* Real name. */ gecos: crate::Gecos, /* Real name. */
home_dir: crate::HomeDir, /* Home directory. */ home_dir: crate::HomeDir, /* Home directory. */
shell_path: crate::ShellPath, /* Shell program. */ shell_path: crate::ShellPath, /* Shell program. */
groups: Vec<(GroupMembership, crate::Group)>,
} }
impl User { impl User {
@ -100,6 +107,7 @@ impl NewFromString for User {
gecos: crate::Gecos::try_from(elements.get(4).unwrap().to_string())?, gecos: crate::Gecos::try_from(elements.get(4).unwrap().to_string())?,
home_dir: crate::HomeDir::try_from(elements.get(5).unwrap().to_string())?, home_dir: crate::HomeDir::try_from(elements.get(5).unwrap().to_string())?,
shell_path: crate::ShellPath::try_from(elements.get(6).unwrap().to_string())?, shell_path: crate::ShellPath::try_from(elements.get(6).unwrap().to_string())?,
groups: Vec::new(),
}) })
} else { } else {
Err("Failed to parse: not enough elements".into()) Err("Failed to parse: not enough elements".into())
@ -204,6 +212,7 @@ impl Default for User {
shell_path: crate::ShellPath { shell_path: crate::ShellPath {
shell: "/bin/nologin".to_owned(), shell: "/bin/nologin".to_owned(),
}, },
groups: Vec::new(),
} }
} }
} }

View File

@ -62,11 +62,12 @@ impl UserDBLocal {
let mut users = user_vec_to_hashmap(string_to(&my_passwd_lines)); let mut users = user_vec_to_hashmap(string_to(&my_passwd_lines));
let passwds: Vec<crate::Shadow> = string_to(&my_shadow_lines); 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); shadow_to_users(&mut users, passwds);
Ok(Self { Ok(Self {
source_files: files, source_files: files,
users, users,
groups: string_to(&my_group_lines), groups,
source_hashes: hashes::Hashes::new(&my_passwd_lines, &my_shadow_lines, &my_group_lines), source_hashes: hashes::Hashes::new(&my_passwd_lines, &my_shadow_lines, &my_group_lines),
}) })
} }
@ -282,8 +283,8 @@ impl UserDBRead for UserDBLocal {
None None
} }
fn get_all_groups(&self) -> Vec<&crate::Group> { fn get_all_groups(&self) -> Vec<crate::Group> {
self.groups.iter().collect() self.groups.iter().map(std::clone::Clone::clone).collect()
} }
fn get_group_by_name(&self, name: &str) -> Option<&crate::Group> { fn get_group_by_name(&self, name: &str) -> Option<&crate::Group> {