restructuring beginn
This commit is contained in:
parent
bceb479c78
commit
8fa154bdd8
13
src/api.rs
13
src/api.rs
@ -20,3 +20,16 @@ trait UserDBWrite {
|
||||
fn set_group(&self) -> Option<crate::Group>;
|
||||
fn new_group(&self) -> Option<crate::Group>;
|
||||
}
|
||||
|
||||
trait UserRead {
|
||||
fn get_username(&self) -> Option<crate::Passwd>;
|
||||
fn get_uid(&self) -> Option<crate::Passwd>;
|
||||
fn get_gid(&self) -> Option<crate::Passwd>;
|
||||
// …
|
||||
}
|
||||
|
||||
trait UserWrite {}
|
||||
|
||||
trait GroupRead {}
|
||||
|
||||
trait GroupWrite {}
|
||||
|
@ -1,7 +1,7 @@
|
||||
extern crate adduser;
|
||||
|
||||
use adduser::passwd::Passwd;
|
||||
use adduser::shadow::Shadow;
|
||||
use adduser::Passwd;
|
||||
use adduser::Shadow;
|
||||
use std::fs::File;
|
||||
use std::io::{prelude::*, BufReader};
|
||||
|
@ -10,7 +10,6 @@
|
||||
use log::warn;
|
||||
use regex::Regex;
|
||||
|
||||
use crate::passwd;
|
||||
use crate::userlib_error::UserLibError;
|
||||
use std::cmp::Eq;
|
||||
use std::convert::TryFrom;
|
||||
@ -41,7 +40,7 @@ impl<'a> TryFrom<&'a str> for Groupname<'a> {
|
||||
Ok(Self { groupname: source })
|
||||
} else {
|
||||
Err(UserLibError::Message(format!(
|
||||
"Invalid username {}",
|
||||
"Invalid groupname -{}-",
|
||||
source
|
||||
)))
|
||||
}
|
||||
@ -51,10 +50,10 @@ impl<'a> TryFrom<&'a str> for Groupname<'a> {
|
||||
/// A record(line) in the user database `/etc/shadow` found in most linux systems.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Group<'a> {
|
||||
groupname: Groupname<'a>, /* Username. */
|
||||
pub(crate) password: passwd::Password<'a>, /* Usually not used (disabled with x) */
|
||||
gid: passwd::Gid, /* Group ID. */
|
||||
members: Vec<passwd::Username<'a>>, /* Real name. */
|
||||
groupname: Groupname<'a>, /* Username. */
|
||||
pub(crate) password: crate::Password<'a>, /* Usually not used (disabled with x) */
|
||||
gid: crate::Gid, /* Group ID. */
|
||||
members: Vec<crate::Username<'a>>, /* Real name. */
|
||||
}
|
||||
|
||||
impl<'a> Group<'a> {
|
||||
@ -63,7 +62,7 @@ impl<'a> Group<'a> {
|
||||
self.groupname.groupname
|
||||
}
|
||||
#[must_use]
|
||||
pub const fn get_members(&self) -> &Vec<passwd::Username<'a>> {
|
||||
pub const fn get_members(&self) -> &Vec<crate::Username<'a>> {
|
||||
&self.members
|
||||
}
|
||||
}
|
||||
@ -104,8 +103,8 @@ impl<'a> Group<'a> {
|
||||
if elements.len() == 4 {
|
||||
Ok(Group {
|
||||
groupname: Groupname::try_from(*elements.get(0).unwrap())?,
|
||||
password: passwd::Password::Disabled,
|
||||
gid: passwd::Gid::try_from(*elements.get(2).unwrap())?,
|
||||
password: crate::Password::Disabled,
|
||||
gid: crate::Gid::try_from(*elements.get(2).unwrap())?,
|
||||
members: parse_members_list(*elements.get(3).unwrap()),
|
||||
})
|
||||
} else {
|
||||
@ -118,17 +117,16 @@ impl<'a> Group<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_members_list<'a>(source: &'a str) -> Vec<passwd::Username<'a>> {
|
||||
fn parse_members_list<'a>(source: &'a str) -> Vec<crate::Username<'a>> {
|
||||
let mut res = vec![];
|
||||
for mem in source.split(',') {
|
||||
res.push(passwd::Username::try_from(mem).expect("failed to parse username"));
|
||||
for mem in source.split(',').filter(|x| !x.is_empty()) {
|
||||
res.push(crate::Username::try_from(mem).expect("failed to parse username"));
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_and_back_identity() {
|
||||
println!("Test");
|
||||
let line = "teste:x:1002:test,teste";
|
||||
let line2 = Group::new_from_string(line).unwrap();
|
||||
assert_eq!(format!("{}", line2), line);
|
||||
@ -136,8 +134,13 @@ fn test_parse_and_back_identity() {
|
||||
|
||||
#[test]
|
||||
fn test_groupname() {
|
||||
println!("Test");
|
||||
let line = "teste:x:1002:test,teste";
|
||||
let line2 = Group::new_from_string(line).unwrap();
|
||||
assert_eq!(line2.get_groupname(), "teste");
|
||||
}
|
||||
#[test]
|
||||
fn test_root_group() {
|
||||
let line = "root:x:0:";
|
||||
let line2 = Group::new_from_string(line).unwrap();
|
||||
assert_eq!(line2.get_groupname(), "root");
|
||||
}
|
@ -5,10 +5,11 @@ extern crate log;
|
||||
|
||||
pub mod api;
|
||||
pub mod group;
|
||||
pub mod passwd;
|
||||
pub mod shadow;
|
||||
pub mod user;
|
||||
pub mod userlib;
|
||||
pub mod userlib_error;
|
||||
pub use group::Group;
|
||||
pub use passwd::{Gecos, Gid, HomeDir, Passwd, Password, ShellPath, Uid, Username};
|
||||
pub use shadow::Shadow;
|
||||
pub use user::passwd_fields::{
|
||||
EncryptedPassword, Gecos, Gid, HomeDir, Passwd, Password, ShellPath, Uid, Username,
|
||||
};
|
||||
pub use user::shadow_fields::Shadow;
|
||||
|
14
src/user/mod.rs
Normal file
14
src/user/mod.rs
Normal file
@ -0,0 +1,14 @@
|
||||
pub mod passwd_fields;
|
||||
pub mod shadow_fields;
|
||||
/// A record(line) in the user database `/etc/passwd` found in most linux systems.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct User<'a> {
|
||||
source: &'a str,
|
||||
username: crate::Username<'a>, /* Username. */
|
||||
password: crate::Password<'a>, /* Hashed passphrase, if shadow database not in use (see shadow.h). */
|
||||
uid: crate::Uid, /* User ID. */
|
||||
gid: crate::Gid, /* Group ID. */
|
||||
gecos: crate::Gecos<'a>, /* Real name. */
|
||||
home_dir: crate::HomeDir<'a>, /* Home directory. */
|
||||
shell_path: crate::ShellPath<'a>, /* Shell program. */
|
||||
}
|
@ -56,7 +56,7 @@ impl<'a> TryFrom<&'a str> for Username<'a> {
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Password<'a> {
|
||||
Encrypted(EncryptedPassword<'a>),
|
||||
Shadow(crate::shadow::Shadow<'a>),
|
||||
Shadow(crate::Shadow<'a>),
|
||||
Disabled,
|
||||
}
|
||||
|
||||
@ -333,6 +333,7 @@ impl<'a> TryFrom<&'a str> for ShellPath<'a> {
|
||||
/// A record(line) in the user database `/etc/passwd` found in most linux systems.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Passwd<'a> {
|
||||
source: &'a str,
|
||||
username: Username<'a>, /* Username. */
|
||||
password: Password<'a>, /* Hashed passphrase, if shadow database not in use (see shadow.h). */
|
||||
uid: Uid, /* User ID. */
|
||||
@ -359,6 +360,7 @@ impl<'a> Passwd<'a> {
|
||||
let elements: Vec<&str> = line.split(':').collect();
|
||||
if elements.len() == 7 {
|
||||
Ok(Passwd {
|
||||
source: line,
|
||||
username: Username::try_from(*elements.get(0).unwrap())?,
|
||||
password: Password::Encrypted(EncryptedPassword::try_from(
|
||||
*elements.get(1).unwrap(),
|
||||
@ -381,7 +383,7 @@ impl<'a> Passwd<'a> {
|
||||
pub const fn get_password(&self) -> &'a str {
|
||||
match self.password {
|
||||
Password::Encrypted(EncryptedPassword { password }) => password,
|
||||
Password::Shadow(crate::shadow::Shadow { ref password, .. }) => password.password,
|
||||
Password::Shadow(crate::Shadow { ref password, .. }) => password.password,
|
||||
Password::Disabled => "x",
|
||||
}
|
||||
}
|
||||
@ -410,6 +412,7 @@ impl<'a> Passwd<'a> {
|
||||
impl Default for Passwd<'_> {
|
||||
fn default() -> Self {
|
||||
Passwd {
|
||||
source: "",
|
||||
username: Username {
|
||||
username: "defaultuser",
|
||||
},
|
@ -9,7 +9,6 @@
|
||||
|
||||
use log::warn;
|
||||
|
||||
use crate::passwd;
|
||||
use crate::userlib_error::UserLibError;
|
||||
use std::cmp::Eq;
|
||||
use std::convert::TryFrom;
|
||||
@ -18,15 +17,15 @@ use std::fmt::{self, Debug, Display};
|
||||
/// A record(line) in the user database `/etc/shadow` found in most linux systems.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub struct Shadow<'a> {
|
||||
username: passwd::Username<'a>, /* Username. */
|
||||
pub(crate) password: passwd::EncryptedPassword<'a>, /* Hashed passphrase */
|
||||
last_change: Option<chrono::NaiveDateTime>, /* User ID. */
|
||||
earliest_change: Option<chrono::NaiveDateTime>, /* Group ID. */
|
||||
latest_change: Option<chrono::NaiveDateTime>, /* Real name. */
|
||||
warn_period: Option<chrono::Duration>, /* Home directory. */
|
||||
deactivated: Option<chrono::Duration>, /* Shell program. */
|
||||
deactivated_since: Option<chrono::Duration>, /* Shell program. */
|
||||
extensions: Option<u64>, /* Shell program. */
|
||||
username: crate::Username<'a>, /* Username. */
|
||||
pub(crate) password: crate::EncryptedPassword<'a>, /* Hashed passphrase */
|
||||
last_change: Option<chrono::NaiveDateTime>, /* User ID. */
|
||||
earliest_change: Option<chrono::NaiveDateTime>, /* Group ID. */
|
||||
latest_change: Option<chrono::NaiveDateTime>, /* Real name. */
|
||||
warn_period: Option<chrono::Duration>, /* Home directory. */
|
||||
deactivated: Option<chrono::Duration>, /* Shell program. */
|
||||
deactivated_since: Option<chrono::Duration>, /* Shell program. */
|
||||
extensions: Option<u64>, /* Shell program. */
|
||||
}
|
||||
|
||||
impl<'a> Shadow<'a> {
|
||||
@ -97,8 +96,8 @@ impl<'a> Shadow<'a> {
|
||||
if elements.len() == 9 {
|
||||
let extra = elements.get(8).unwrap();
|
||||
Ok(Shadow {
|
||||
username: passwd::Username::try_from(*elements.get(0).unwrap())?,
|
||||
password: passwd::EncryptedPassword::try_from(*elements.get(1).unwrap())?,
|
||||
username: crate::Username::try_from(*elements.get(0).unwrap())?,
|
||||
password: crate::EncryptedPassword::try_from(*elements.get(1).unwrap())?,
|
||||
last_change: date_since_epoch(elements.get(2).unwrap()),
|
||||
earliest_change: date_since_epoch(elements.get(3).unwrap()),
|
||||
latest_change: date_since_epoch(elements.get(4).unwrap()),
|
@ -14,7 +14,8 @@ use crate::userlib_error::UserLibError;
|
||||
use std::cmp::Eq;
|
||||
use std::convert::TryFrom;
|
||||
use std::fmt::{self, Display};
|
||||
use std::io::{BufRead, Read};
|
||||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader, Read};
|
||||
|
||||
pub struct UserDBLocal<'a> {
|
||||
pub(crate) passwd_entries: Vec<crate::Passwd<'a>>,
|
||||
@ -32,15 +33,34 @@ impl<'a> UserDBLocal<'a> {
|
||||
let res = UserDBLocal {
|
||||
passwd_entries: passwd_content
|
||||
.lines()
|
||||
.map(|line| crate::Passwd::new_from_string(line).expect("failed to read lines"))
|
||||
.filter_map(|line| {
|
||||
if line.len() > 5 {
|
||||
println!("{}", line);
|
||||
Some(crate::Passwd::new_from_string(line).expect("failed to read lines"))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
group_entries: group_content
|
||||
.lines()
|
||||
.map(|line| crate::Group::new_from_string(line).expect("Parsing failed"))
|
||||
.filter_map(|line| {
|
||||
if line.len() > 5 {
|
||||
Some(crate::Group::new_from_string(line).expect("Parsing failed"))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
shadow_entries: shadow_content
|
||||
.lines()
|
||||
.map(|line| crate::Shadow::new_from_string(line).expect("Parsing failed"))
|
||||
.filter_map(|line| {
|
||||
if line.len() > 5 {
|
||||
Some(crate::Shadow::new_from_string(line).expect("Parsing failed"))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
res
|
||||
@ -55,3 +75,20 @@ fn test_creator_user_db_local() {
|
||||
"testuser"
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parsing_local_database() {
|
||||
let passwd_file = File::open("/etc/passwd").unwrap();
|
||||
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);
|
||||
assert_eq!(
|
||||
format!("{}", data.group_entries.get(0).unwrap().get_groupname()),
|
||||
"teste"
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user