persistent ordering of the passwd file
This commit is contained in:
		
							parent
							
								
									98d4c72f7f
								
							
						
					
					
						commit
						f33ba8e767
					
				@ -106,15 +106,15 @@ impl NewFromString for Group {
 | 
			
		||||
    /// use crate::adduser::api::GroupRead;
 | 
			
		||||
    /// use adduser::NewFromString;
 | 
			
		||||
    /// let grp = adduser::Group::new_from_string(
 | 
			
		||||
    ///     "teste:x:1002:test,teste".to_owned()
 | 
			
		||||
    ///     "teste:x:1002:test,teste".to_owned(),
 | 
			
		||||
    ///     0,
 | 
			
		||||
    /// ).unwrap();
 | 
			
		||||
    /// assert_eq!(grp.get_groupname().unwrap(), "teste");
 | 
			
		||||
    /// ```
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Errors
 | 
			
		||||
    /// When parsing fails this function returns a `UserLibError::Message` containing some information as to why the function failed.
 | 
			
		||||
    fn new_from_string(line: String) -> Result<Self, UserLibError> {
 | 
			
		||||
        println!("{}", &line);
 | 
			
		||||
    fn new_from_string(line: String, position: u32) -> Result<Self, UserLibError> {
 | 
			
		||||
        let elements: Vec<String> = line.split(':').map(ToString::to_string).collect();
 | 
			
		||||
        if elements.len() == 4 {
 | 
			
		||||
            Ok(Self {
 | 
			
		||||
@ -150,19 +150,19 @@ fn parse_members_list(source: &str) -> Vec<crate::Username> {
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_parse_and_back_identity() {
 | 
			
		||||
    let line = "teste:x:1002:test,teste";
 | 
			
		||||
    let line2 = Group::new_from_string(line.to_owned()).unwrap();
 | 
			
		||||
    let line2 = Group::new_from_string(line.to_owned(), 0).unwrap();
 | 
			
		||||
    assert_eq!(format!("{}", line2), line);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_groupname() {
 | 
			
		||||
    let line = "teste:x:1002:test,teste";
 | 
			
		||||
    let line2 = Group::new_from_string(line.to_owned()).unwrap();
 | 
			
		||||
    let line2 = Group::new_from_string(line.to_owned(), 0).unwrap();
 | 
			
		||||
    assert_eq!(line2.get_groupname().unwrap(), "teste");
 | 
			
		||||
}
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_root_group() {
 | 
			
		||||
    let line = "root:x:0:";
 | 
			
		||||
    let line2 = Group::new_from_string(line.to_owned()).unwrap();
 | 
			
		||||
    let line2 = Group::new_from_string(line.to_owned(), 0).unwrap();
 | 
			
		||||
    assert_eq!(line2.get_groupname().unwrap(), "root");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -205,7 +205,6 @@ fn test_gecos_getters() {
 | 
			
		||||
    assert_eq!(res_simple.get_comment(), Some("A böring comment →"));
 | 
			
		||||
 | 
			
		||||
    assert_eq!(res_detail.get_comment(), None);
 | 
			
		||||
    println!("{:?}", res_detail);
 | 
			
		||||
    assert_eq!(res_detail.get_full_name(), Some("Full Name"));
 | 
			
		||||
    assert_eq!(res_detail.get_room(), Some("504"));
 | 
			
		||||
    assert_eq!(res_detail.get_phone_work(), Some("11345342"));
 | 
			
		||||
 | 
			
		||||
@ -10,6 +10,7 @@ use std::fmt::{self, Display};
 | 
			
		||||
#[derive(Debug, PartialEq, Eq)]
 | 
			
		||||
pub struct User {
 | 
			
		||||
    source: String,
 | 
			
		||||
    pos: u32,
 | 
			
		||||
    username: crate::Username,            /* Username.  */
 | 
			
		||||
    pub(crate) password: crate::Password, /* Hashed passphrase, if shadow database not in use (see shadow.h).  */
 | 
			
		||||
    uid: crate::Uid,                      /* User ID.  */
 | 
			
		||||
@ -27,13 +28,13 @@ impl NewFromString for User {
 | 
			
		||||
    /// use crate::adduser::api::UserRead;
 | 
			
		||||
    /// use adduser::NewFromString;
 | 
			
		||||
    /// let pwd = adduser::User::new_from_string(
 | 
			
		||||
    ///     "testuser:testpassword:1001:1001:full Name,,,,:/home/test:/bin/test".to_string()).unwrap();
 | 
			
		||||
    ///     "testuser:testpassword:1001:1001:full Name,,,,:/home/test:/bin/test".to_string(), 0).unwrap();
 | 
			
		||||
    /// assert_eq!(pwd.get_username().unwrap(), "testuser");
 | 
			
		||||
    /// ```
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Errors
 | 
			
		||||
    /// When parsing fails this function returns a [`UserLibError::Message`](crate::userlib_error::UserLibError::Message) containing some information as to why the function failed.
 | 
			
		||||
    fn new_from_string(line: String) -> Result<Self, crate::UserLibError>
 | 
			
		||||
    fn new_from_string(line: String, position: u32) -> Result<Self, crate::UserLibError>
 | 
			
		||||
    where
 | 
			
		||||
        Self: Sized,
 | 
			
		||||
    {
 | 
			
		||||
@ -41,6 +42,7 @@ impl NewFromString for User {
 | 
			
		||||
        if elements.len() == 7 {
 | 
			
		||||
            Ok(Self {
 | 
			
		||||
                source: line,
 | 
			
		||||
                pos: position,
 | 
			
		||||
                username: crate::Username::try_from(elements.get(0).unwrap().to_string())?,
 | 
			
		||||
                password: crate::Password::Encrypted(crate::EncryptedPassword::try_from(
 | 
			
		||||
                    elements.get(1).unwrap().to_string(),
 | 
			
		||||
@ -112,10 +114,23 @@ impl crate::api::UserRead for User {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl PartialOrd for User {
 | 
			
		||||
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
 | 
			
		||||
        Some(self.pos.cmp(&other.pos))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Ord for User {
 | 
			
		||||
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
 | 
			
		||||
        self.pos.cmp(&other.pos)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl Default for User {
 | 
			
		||||
    fn default() -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            source: "".to_owned(),
 | 
			
		||||
            pos: u32::MAX,
 | 
			
		||||
            username: crate::Username {
 | 
			
		||||
                username: "defaultuser".to_owned(),
 | 
			
		||||
            },
 | 
			
		||||
@ -165,17 +180,18 @@ fn test_default_user() {
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_new_from_string() {
 | 
			
		||||
    // Test if a single line can be parsed and if the resulting struct is populated correctly.
 | 
			
		||||
    let fail = User::new_from_string("".into()).err().unwrap();
 | 
			
		||||
    let fail = User::new_from_string("".into(), 0).err().unwrap();
 | 
			
		||||
    assert_eq!(
 | 
			
		||||
        fail,
 | 
			
		||||
        crate::UserLibError::Message("Failed to parse: not enough elements".into())
 | 
			
		||||
    );
 | 
			
		||||
    let pwd = User::new_from_string(
 | 
			
		||||
        "testuser:testpassword:1001:1001:testcomment:/home/test:/bin/test".into(),
 | 
			
		||||
        0,
 | 
			
		||||
    )
 | 
			
		||||
    .unwrap();
 | 
			
		||||
    let pwd2 =
 | 
			
		||||
        User::new_from_string("testuser:testpassword:1001:1001:full Name,004,000342,001-2312,myemail@test.com:/home/test:/bin/test".into())
 | 
			
		||||
        User::new_from_string("testuser:testpassword:1001:1001:full Name,004,000342,001-2312,myemail@test.com:/home/test:/bin/test".into(),0)
 | 
			
		||||
            .unwrap();
 | 
			
		||||
    assert_eq!(pwd.username.username, "testuser");
 | 
			
		||||
    assert_eq!(pwd.home_dir.dir, "/home/test");
 | 
			
		||||
@ -210,10 +226,10 @@ fn test_parse_passwd() {
 | 
			
		||||
    let file = File::open("/etc/passwd").unwrap();
 | 
			
		||||
    let reader = BufReader::new(file);
 | 
			
		||||
 | 
			
		||||
    for line in reader.lines() {
 | 
			
		||||
    for (n, line) in reader.lines().enumerate() {
 | 
			
		||||
        let lineorig: String = line.unwrap();
 | 
			
		||||
        let linecopy = lineorig.clone();
 | 
			
		||||
        let pass_struc = User::new_from_string(linecopy).unwrap();
 | 
			
		||||
        let pass_struc = User::new_from_string(linecopy, n as u32).unwrap();
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            // ignoring the numbers of `,` since the implementation does not (yet) reproduce a missing comment field.
 | 
			
		||||
            lineorig,
 | 
			
		||||
 | 
			
		||||
@ -85,15 +85,15 @@ impl NewFromString for Shadow {
 | 
			
		||||
    /// ```
 | 
			
		||||
    /// use adduser::NewFromString;
 | 
			
		||||
    /// let shad = adduser::Shadow::new_from_string(
 | 
			
		||||
    ///     "test:!!$6$/RotIe4VZzzAun4W$7YUONvru1rDnllN5TvrnOMsWUD5wSDUPAD6t6/Xwsr/0QOuWF3HcfAhypRkGa8G1B9qqWV5kZSnCb8GKMN9N61:18260:0:99999:7:::".to_string()
 | 
			
		||||
    ///     "test:!!$6$/RotIe4VZzzAun4W$7YUONvru1rDnllN5TvrnOMsWUD5wSDUPAD6t6/Xwsr/0QOuWF3HcfAhypRkGa8G1B9qqWV5kZSnCb8GKMN9N61:18260:0:99999:7:::".to_string(),
 | 
			
		||||
    ///     0,
 | 
			
		||||
    /// ).unwrap();
 | 
			
		||||
    /// assert_eq!(shad.get_username(), "test");
 | 
			
		||||
    /// ```
 | 
			
		||||
    ///
 | 
			
		||||
    /// # Errors
 | 
			
		||||
    /// When parsing fails this function returns a `UserLibError::Message` containing some information as to why the function failed.
 | 
			
		||||
    fn new_from_string(line: String) -> Result<Self, UserLibError> {
 | 
			
		||||
        println!("{}", &line);
 | 
			
		||||
    fn new_from_string(line: String, position: u32) -> Result<Self, UserLibError> {
 | 
			
		||||
        let elements: Vec<String> = line.split(':').map(ToString::to_string).collect();
 | 
			
		||||
        if elements.len() == 9 {
 | 
			
		||||
            let extra = elements.get(8).unwrap();
 | 
			
		||||
@ -144,9 +144,7 @@ fn duration_for_days(days_source: &str) -> Option<chrono::Duration> {
 | 
			
		||||
 | 
			
		||||
#[test]
 | 
			
		||||
fn test_parse_and_back_identity() {
 | 
			
		||||
    println!("Test");
 | 
			
		||||
    let line = "test:!!$6$/RotIe4VZzzAun4W$7YUONvru1rDnllN5TvrnOMsWUD5wSDUPAD6t6/Xwsr/0QOuWF3HcfAhypRkGa8G1B9qqWV5kZSnCb8GKMN9N61:18260:0:99999:7:::";
 | 
			
		||||
    let line2 = Shadow::new_from_string(line.to_owned()).unwrap();
 | 
			
		||||
    println!("{:#?}", line2);
 | 
			
		||||
    let line2 = Shadow::new_from_string(line.to_owned(), 0).unwrap();
 | 
			
		||||
    assert_eq!(format!("{}", line2), line);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -145,7 +145,9 @@ impl UserDBWrite for UserDBLocal {
 | 
			
		||||
use crate::api::UserDBRead;
 | 
			
		||||
impl UserDBRead for UserDBLocal {
 | 
			
		||||
    fn get_all_users(&self) -> Vec<&crate::User> {
 | 
			
		||||
        self.users.iter().map(|(_, x)| x).collect()
 | 
			
		||||
        let mut res: Vec<&crate::User> = self.users.iter().map(|(_, x)| x).collect();
 | 
			
		||||
        res.sort();
 | 
			
		||||
        res
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn get_user_by_name(&self, name: &str) -> Option<&crate::User> {
 | 
			
		||||
@ -258,7 +260,7 @@ fn user_vec_to_hashmap(users: Vec<crate::User>) -> HashMap<String, crate::User>
 | 
			
		||||
/// # Errors
 | 
			
		||||
/// if the parsing failed a [`UserLibError::Message`](crate::userlib_error::UserLibError::Message) is returned containing a more detailed error message.
 | 
			
		||||
pub trait NewFromString {
 | 
			
		||||
    fn new_from_string(line: String) -> Result<Self, crate::UserLibError>
 | 
			
		||||
    fn new_from_string(line: String, position: u32) -> Result<Self, crate::UserLibError>
 | 
			
		||||
    where
 | 
			
		||||
        Self: Sized;
 | 
			
		||||
}
 | 
			
		||||
@ -270,10 +272,10 @@ where
 | 
			
		||||
{
 | 
			
		||||
    source
 | 
			
		||||
        .lines()
 | 
			
		||||
        .filter_map(|line| {
 | 
			
		||||
        .enumerate()
 | 
			
		||||
        .filter_map(|(n, line)| {
 | 
			
		||||
            if line.len() > 5 {
 | 
			
		||||
                //println!("{}", line);
 | 
			
		||||
                Some(T::new_from_string(line.to_owned()).expect("failed to read lines"))
 | 
			
		||||
                Some(T::new_from_string(line.to_owned(), n as u32).expect("failed to read lines"))
 | 
			
		||||
            } else {
 | 
			
		||||
                None
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user