linting changes
This commit is contained in:
parent
647881f022
commit
467c8ee007
@ -1,3 +1,4 @@
|
||||
#![allow(clippy::default_trait_access)]
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
@ -12,7 +13,6 @@ pub enum DeletePrimaryGroup {
|
||||
Keep,
|
||||
DeleteIfEmpty,
|
||||
}
|
||||
|
||||
#[derive(Debug, Builder, Eq, PartialEq)]
|
||||
#[builder(public)]
|
||||
#[builder(default)]
|
||||
@ -23,6 +23,7 @@ pub struct NewUserArgs<'a> {
|
||||
}
|
||||
|
||||
impl<'a> NewUserArgs<'a> {
|
||||
#[must_use]
|
||||
pub fn builder() -> NewUserArgsBuilder<'a> {
|
||||
NewUserArgsBuilder::default()
|
||||
}
|
||||
|
@ -2,6 +2,9 @@ use std::path::PathBuf;
|
||||
|
||||
extern crate adduser;
|
||||
|
||||
use adduser::api::UserDBWrite;
|
||||
use adduser::api::UserRead;
|
||||
|
||||
extern crate env_logger;
|
||||
#[allow(unused_imports)]
|
||||
use log::{debug, error, info, trace, warn};
|
||||
@ -9,9 +12,6 @@ use log::{debug, error, info, trace, warn};
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
||||
use adduser::api::UserDBWrite;
|
||||
use adduser::api::UserRead;
|
||||
|
||||
let mf = adduser::Files {
|
||||
passwd: Some(PathBuf::from("./passwd")),
|
||||
shadow: Some(PathBuf::from("./shadow")),
|
||||
|
@ -1,4 +1,5 @@
|
||||
extern crate adduser;
|
||||
use adduser::api::UserDBRead;
|
||||
|
||||
fn main() {
|
||||
simplelog::CombinedLogger::init(vec![simplelog::TermLogger::new(
|
||||
@ -7,7 +8,6 @@ fn main() {
|
||||
simplelog::TerminalMode::Mixed,
|
||||
)])
|
||||
.unwrap();
|
||||
use adduser::api::UserDBRead;
|
||||
|
||||
let db = adduser::UserDBLocal::load_files(adduser::Files::default()).unwrap();
|
||||
|
||||
|
24
src/error.rs
24
src/error.rs
@ -1,6 +1,7 @@
|
||||
use std::error::Error;
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum ParseError {
|
||||
Username,
|
||||
@ -12,6 +13,7 @@ pub enum ParseError {
|
||||
ShellDir,
|
||||
}
|
||||
|
||||
#[allow(clippy::module_name_repetitions)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub enum UserLibError {
|
||||
NotFound,
|
||||
@ -36,8 +38,8 @@ impl PartialEq for MyMessage {
|
||||
impl Display for MyMessage {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
MyMessage::Simple(m) => write!(f, "{}", m),
|
||||
MyMessage::IOError(m, e) => write!(f, "{},{}", m, e),
|
||||
Self::Simple(m) => write!(f, "{}", m),
|
||||
Self::IOError(m, e) => write!(f, "{},{}", m, e),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -47,7 +49,7 @@ impl Display for UserLibError {
|
||||
match self {
|
||||
Self::NotFound => write!(f, "not found"),
|
||||
Self::ParseError => write!(f, "failed to parse"),
|
||||
UserLibError::FilesRequired => write!(
|
||||
Self::FilesRequired => write!(
|
||||
f,
|
||||
"File locking is only possible if some files are specified"
|
||||
),
|
||||
@ -63,12 +65,12 @@ impl Display for UserLibError {
|
||||
impl Error for UserLibError {
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
match *self {
|
||||
UserLibError::NotFound
|
||||
| UserLibError::ParseError
|
||||
| UserLibError::FilesChanged
|
||||
| UserLibError::FilesRequired => None,
|
||||
UserLibError::Message(MyMessage::IOError(_, ref e)) => Some(e),
|
||||
UserLibError::Message(MyMessage::Simple(_)) => None,
|
||||
Self::NotFound
|
||||
| Self::ParseError
|
||||
| Self::FilesChanged
|
||||
| Self::FilesRequired
|
||||
| Self::Message(MyMessage::Simple(_)) => None,
|
||||
Self::Message(MyMessage::IOError(_, ref e)) => Some(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -87,13 +89,13 @@ impl From<String> for UserLibError {
|
||||
|
||||
impl From<std::io::Error> for UserLibError {
|
||||
fn from(e: std::io::Error) -> Self {
|
||||
UserLibError::Message(MyMessage::Simple(e.to_string()))
|
||||
Self::Message(MyMessage::Simple(e.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(String, std::io::Error)> for UserLibError {
|
||||
fn from((m, e): (String, std::io::Error)) -> Self {
|
||||
UserLibError::Message(MyMessage::IOError(m, e))
|
||||
Self::Message(MyMessage::IOError(m, e))
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
@ -1,10 +1,3 @@
|
||||
#![warn(
|
||||
clippy::all,
|
||||
/* clippy::restriction,*/
|
||||
clippy::pedantic,
|
||||
clippy::nursery,
|
||||
clippy::cargo
|
||||
)]
|
||||
#![allow(clippy::non_ascii_literal)]
|
||||
|
||||
use crate::userlib::NewFromString;
|
||||
@ -57,10 +50,11 @@ pub struct Group {
|
||||
}
|
||||
|
||||
impl Group {
|
||||
#[must_use]
|
||||
pub fn remove_in(&self, content: &str) -> String {
|
||||
content
|
||||
.split(&self.source)
|
||||
.map(|x| x.trim())
|
||||
.map(str::trim)
|
||||
.collect::<Vec<&str>>()
|
||||
.join("\n")
|
||||
}
|
||||
@ -75,7 +69,7 @@ impl GroupRead for Group {
|
||||
#[must_use]
|
||||
fn get_member_names(&self) -> Option<Vec<&str>> {
|
||||
let mut r: Vec<&str> = Vec::new();
|
||||
for u in self.members.iter() {
|
||||
for u in &self.members {
|
||||
r.push(&u.username);
|
||||
}
|
||||
Some(r)
|
||||
@ -128,7 +122,7 @@ impl NewFromString for Group {
|
||||
if elements.len() == 4 {
|
||||
Ok(Self {
|
||||
pos: position,
|
||||
source: line.clone(),
|
||||
source: line,
|
||||
groupname: Groupname::try_from(elements.get(0).unwrap().to_string())?,
|
||||
password: crate::Password::Disabled,
|
||||
gid: crate::Gid::try_from(elements.get(2).unwrap().to_string())?,
|
||||
|
@ -1,3 +1,12 @@
|
||||
#![warn(
|
||||
clippy::all,
|
||||
//clippy::restriction,
|
||||
clippy::pedantic,
|
||||
clippy::nursery,
|
||||
clippy::cargo
|
||||
)]
|
||||
//#![allow(clippy::non_ascii_literal)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
|
@ -1,3 +1,4 @@
|
||||
#![allow(clippy::non_ascii_literal)]
|
||||
use crate::UserLibError;
|
||||
use std::cmp::Eq;
|
||||
use std::convert::TryFrom;
|
||||
@ -26,19 +27,19 @@ impl Gecos {
|
||||
#[must_use]
|
||||
pub fn get_comment(&self) -> Option<&str> {
|
||||
match &self {
|
||||
Gecos::Simple { comment, .. } => Some(&comment),
|
||||
Gecos::Detail { .. } => None,
|
||||
Self::Simple { comment, .. } => Some(comment),
|
||||
Self::Detail { .. } => None,
|
||||
}
|
||||
}
|
||||
#[must_use]
|
||||
pub fn get_full_name(&self) -> Option<&str> {
|
||||
match &self {
|
||||
Gecos::Simple { .. } => None,
|
||||
Gecos::Detail { full_name, .. } => {
|
||||
Self::Simple { .. } => None,
|
||||
Self::Detail { full_name, .. } => {
|
||||
if full_name.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(&full_name)
|
||||
Some(full_name)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -46,12 +47,12 @@ impl Gecos {
|
||||
#[must_use]
|
||||
pub fn get_room(&self) -> Option<&str> {
|
||||
match &self {
|
||||
Gecos::Simple { .. } => None,
|
||||
Gecos::Detail { room, .. } => {
|
||||
Self::Simple { .. } => None,
|
||||
Self::Detail { room, .. } => {
|
||||
if room.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(&room)
|
||||
Some(room)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -59,12 +60,12 @@ impl Gecos {
|
||||
#[must_use]
|
||||
pub fn get_phone_work(&self) -> Option<&str> {
|
||||
match &self {
|
||||
Gecos::Simple { .. } => None,
|
||||
Gecos::Detail { phone_work, .. } => {
|
||||
Self::Simple { .. } => None,
|
||||
Self::Detail { phone_work, .. } => {
|
||||
if phone_work.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(&phone_work)
|
||||
Some(phone_work)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -72,12 +73,12 @@ impl Gecos {
|
||||
#[must_use]
|
||||
pub fn get_phone_home(&self) -> Option<&str> {
|
||||
match &self {
|
||||
Gecos::Simple { .. } => None,
|
||||
Gecos::Detail { phone_home, .. } => {
|
||||
Self::Simple { .. } => None,
|
||||
Self::Detail { phone_home, .. } => {
|
||||
if phone_home.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(&phone_home)
|
||||
Some(phone_home)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,8 +86,8 @@ impl Gecos {
|
||||
#[must_use]
|
||||
pub const fn get_other(&self) -> Option<&Vec<String>> {
|
||||
match self {
|
||||
Gecos::Simple { .. } => None,
|
||||
Gecos::Detail { other, .. } => match other {
|
||||
Self::Simple { .. } => None,
|
||||
Self::Detail { other, .. } => match other {
|
||||
None => None,
|
||||
Some(comments) => Some(comments),
|
||||
},
|
||||
@ -97,8 +98,8 @@ impl Gecos {
|
||||
impl Display for Gecos {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match &self {
|
||||
Gecos::Simple { comment } => write!(f, "{}", comment),
|
||||
Gecos::Detail {
|
||||
Self::Simple { comment } => write!(f, "{}", comment),
|
||||
Self::Detail {
|
||||
full_name,
|
||||
room,
|
||||
phone_work,
|
||||
@ -125,7 +126,7 @@ impl TryFrom<String> for Gecos {
|
||||
fn try_from(source: String) -> std::result::Result<Self, Self::Error> {
|
||||
let vals: Vec<String> = source.split(',').map(ToString::to_string).collect();
|
||||
if vals.len() > 3 {
|
||||
Ok(Gecos::Detail {
|
||||
Ok(Self::Detail {
|
||||
full_name: vals[0].clone(),
|
||||
room: vals[1].clone(),
|
||||
phone_work: vals[2].clone(),
|
||||
@ -137,7 +138,7 @@ impl TryFrom<String> for Gecos {
|
||||
},
|
||||
})
|
||||
} else if vals.len() == 1 {
|
||||
Ok(Gecos::Simple {
|
||||
Ok(Self::Simple {
|
||||
comment: vals.get(0).unwrap().into(),
|
||||
})
|
||||
} else {
|
||||
@ -145,7 +146,6 @@ impl TryFrom<String> for Gecos {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_gecos() {
|
||||
// test if the Gecos field can be parsed and the resulting struct is populated correctly.
|
||||
|
@ -24,11 +24,11 @@ pub struct User {
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub fn get_shadow(&self) -> Option<&crate::Shadow> {
|
||||
#[must_use]
|
||||
pub const fn get_shadow(&self) -> Option<&crate::Shadow> {
|
||||
match self.password {
|
||||
crate::Password::Encrypted(_) => None,
|
||||
crate::Password::Encrypted(_) | crate::Password::Disabled => None,
|
||||
crate::Password::Shadow(ref s) => Some(s),
|
||||
crate::Password::Disabled => None,
|
||||
}
|
||||
}
|
||||
/*fn get_nth_line(content: &str, n: u32) -> (String, u64) {
|
||||
@ -49,17 +49,16 @@ impl User {
|
||||
trace!("Olduser:\n\t{}\nNewuser\n\t{}", &self.source, &line);
|
||||
(offset, line.len(), line == self.source)
|
||||
}*/
|
||||
#[must_use]
|
||||
pub fn remove_in(&self, content: &str) -> String {
|
||||
content
|
||||
.split(&self.source)
|
||||
.map(|x| x.trim())
|
||||
.map(str::trim)
|
||||
.collect::<Vec<&str>>()
|
||||
.join("\n")
|
||||
}
|
||||
pub fn username(&mut self, name: String) -> &mut Self {
|
||||
self.username = crate::Username {
|
||||
username: name.into(),
|
||||
};
|
||||
self.username = crate::Username { username: name };
|
||||
self
|
||||
}
|
||||
pub fn disable_password(&mut self) -> &mut Self {
|
||||
@ -131,7 +130,7 @@ impl crate::api::UserRead for User {
|
||||
#[must_use]
|
||||
fn get_password(&self) -> Option<&str> {
|
||||
match &self.password {
|
||||
crate::Password::Encrypted(crate::EncryptedPassword { password }) => Some(&password),
|
||||
crate::Password::Encrypted(crate::EncryptedPassword { password }) => Some(password),
|
||||
crate::Password::Shadow(crate::Shadow { ref password, .. }) => Some(&password.password),
|
||||
crate::Password::Disabled => None,
|
||||
}
|
||||
@ -287,6 +286,7 @@ fn test_new_from_string() {
|
||||
#[test]
|
||||
fn test_parse_passwd() {
|
||||
// Test wether the passwd file can be parsed and recreated without throwing an exception
|
||||
use std::convert::TryInto;
|
||||
use std::fs::File;
|
||||
use std::io::{prelude::*, BufReader};
|
||||
let file = File::open("/etc/passwd").unwrap();
|
||||
@ -295,7 +295,7 @@ fn test_parse_passwd() {
|
||||
for (n, line) in reader.lines().enumerate() {
|
||||
let lineorig: String = line.unwrap();
|
||||
let linecopy = lineorig.clone();
|
||||
let pass_struc = User::new_from_string(linecopy, n as u32).unwrap();
|
||||
let pass_struc = User::new_from_string(linecopy, n.try_into().unwrap()).unwrap();
|
||||
assert_eq!(
|
||||
// ignoring the numbers of `,` since the implementation does not (yet) reproduce a missing comment field.
|
||||
lineorig,
|
||||
|
@ -1,10 +1,3 @@
|
||||
#![warn(
|
||||
clippy::all,
|
||||
/* clippy::restriction,*/
|
||||
clippy::pedantic,
|
||||
clippy::nursery,
|
||||
clippy::cargo
|
||||
)]
|
||||
#![allow(clippy::non_ascii_literal)]
|
||||
|
||||
use log::warn;
|
||||
@ -65,8 +58,7 @@ impl Display for Password {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Encrypted(EncryptedPassword { password }) => write!(f, "{}", password,),
|
||||
Self::Shadow(_) => write!(f, "x"),
|
||||
Self::Disabled => write!(f, "x"),
|
||||
Self::Shadow(_) | Self::Disabled => write!(f, "x"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -85,11 +77,11 @@ impl Display for EncryptedPassword {
|
||||
impl TryFrom<String> for EncryptedPassword {
|
||||
type Error = UserLibError;
|
||||
fn try_from(source: String) -> std::result::Result<Self, Self::Error> {
|
||||
if source == "x" {
|
||||
/*if source == "x" {
|
||||
//warn!("password from shadow not loaded!")
|
||||
} else {
|
||||
//warn!("Password field has an unexpected value")
|
||||
};
|
||||
};*/
|
||||
Ok(Self { password: source })
|
||||
}
|
||||
}
|
||||
@ -149,6 +141,7 @@ impl Gid {
|
||||
self.gid < 1000
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub const fn get_gid(&self) -> u32 {
|
||||
self.gid
|
||||
}
|
||||
|
@ -1,14 +1,4 @@
|
||||
#![warn(
|
||||
clippy::all,
|
||||
/* clippy::restriction,*/
|
||||
clippy::pedantic,
|
||||
clippy::nursery,
|
||||
clippy::cargo
|
||||
)]
|
||||
#![allow(clippy::non_ascii_literal)]
|
||||
|
||||
use crate::userlib::NewFromString;
|
||||
use log::warn;
|
||||
|
||||
use crate::UserLibError;
|
||||
use std::cmp::Eq;
|
||||
@ -40,10 +30,11 @@ impl Shadow {
|
||||
pub fn get_password(&self) -> &str {
|
||||
&self.password.password
|
||||
}
|
||||
#[must_use]
|
||||
pub fn remove_in(&self, content: &str) -> String {
|
||||
content
|
||||
.split(&self.source)
|
||||
.map(|x| x.trim())
|
||||
.map(str::trim)
|
||||
.collect::<Vec<&str>>()
|
||||
.join("\n")
|
||||
}
|
||||
@ -108,7 +99,7 @@ impl NewFromString for Shadow {
|
||||
let extra = elements.get(8).unwrap();
|
||||
Ok(Self {
|
||||
pos: position,
|
||||
source: line.clone(),
|
||||
source: line,
|
||||
username: crate::Username::try_from(elements.get(0).unwrap().to_string())?,
|
||||
password: crate::EncryptedPassword::try_from(elements.get(1).unwrap().to_string())?,
|
||||
last_change: date_since_epoch(elements.get(2).unwrap()),
|
||||
|
@ -26,7 +26,8 @@ impl Default for Files {
|
||||
|
||||
impl Files {
|
||||
/// Check if all the files are defined. Because some operations require the files to be present
|
||||
pub fn is_virtual(&self) -> bool {
|
||||
#[must_use]
|
||||
pub const fn is_virtual(&self) -> bool {
|
||||
!(self.group.is_some() & self.passwd.is_some() & self.shadow.is_some())
|
||||
}
|
||||
pub fn lock_and_get_passwd(&self) -> Result<LockedFileGuard, crate::UserLibError> {
|
||||
@ -89,7 +90,7 @@ impl LockedFileGuard {
|
||||
Ok(_) => (),
|
||||
Err(e) => return Err(("Could not write (all) users. ".to_owned(), e).into()),
|
||||
};
|
||||
let _ = self.file.write("\n".as_bytes());
|
||||
let _ = self.file.write(b"\n");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -155,12 +156,19 @@ impl LockedFileGuard {
|
||||
);
|
||||
// write the pid into the tempfile
|
||||
{
|
||||
let mut tempfile = File::create(&*tempfilepath)
|
||||
.expect(&format!("Failed to open {}", filename.to_str().unwrap()));
|
||||
match write!(tempfile, "{}", pid) {
|
||||
Ok(_) => {}
|
||||
Err(_) => error!("could not write to {}", filename.to_string_lossy()),
|
||||
};
|
||||
let mut tempfile = File::create(&*tempfilepath).unwrap_or_else(|e| {
|
||||
panic!("Failed to open {} error: {}", filename.to_str().unwrap(), e)
|
||||
});
|
||||
write!(tempfile, "{}", pid).or_else(|e| {
|
||||
let error_msg = format!(
|
||||
"could not write to {} error {}",
|
||||
filename.to_string_lossy(),
|
||||
e
|
||||
);
|
||||
error!("{}", error_msg);
|
||||
let err: crate::UserLibError = error_msg.into();
|
||||
Err(err)
|
||||
})?;
|
||||
}
|
||||
|
||||
// try to make a hardlink from the lockfile to the tempfile
|
||||
@ -198,12 +206,9 @@ impl LockedFileGuard {
|
||||
}
|
||||
};
|
||||
let mut content = String::new();
|
||||
match lf.read_to_string(&mut content) {
|
||||
Ok(_) => {}
|
||||
Err(_) => {
|
||||
panic!("failed to read the lockfile{}", e);
|
||||
}
|
||||
}
|
||||
lf.read_to_string(&mut content)
|
||||
.unwrap_or_else(|e| panic!("failed to read the lockfile{}", e));
|
||||
|
||||
let content = content.trim().trim_matches(char::from(0));
|
||||
let lock_pid = content.parse::<u32>();
|
||||
match lock_pid {
|
||||
|
@ -5,11 +5,13 @@ pub struct SourceHash {
|
||||
}
|
||||
|
||||
impl SourceHash {
|
||||
#[must_use]
|
||||
pub fn new(src: &str) -> Self {
|
||||
Self {
|
||||
hashvalue: src.to_owned(),
|
||||
}
|
||||
}
|
||||
#[must_use]
|
||||
pub fn has_changed(&self, new: &str) -> bool {
|
||||
trace!(
|
||||
"Old and new lengths: {}, {}",
|
||||
@ -27,6 +29,7 @@ pub struct Hashes {
|
||||
}
|
||||
|
||||
impl Hashes {
|
||||
#[must_use]
|
||||
pub fn new(passwd: &str, shadow: &str, group: &str) -> Self {
|
||||
Self {
|
||||
passwd: SourceHash::new(passwd),
|
||||
|
@ -1,10 +1,3 @@
|
||||
#![warn(
|
||||
clippy::all,
|
||||
//clippy::restriction,
|
||||
clippy::pedantic,
|
||||
clippy::nursery,
|
||||
clippy::cargo
|
||||
)]
|
||||
#![allow(clippy::non_ascii_literal)]
|
||||
|
||||
pub mod files;
|
||||
@ -33,11 +26,11 @@ impl UserDBLocal {
|
||||
shadow_content: &str,
|
||||
group_content: &str,
|
||||
) -> Self {
|
||||
let shadow_entries: Vec<crate::Shadow> = string_to(&shadow_content);
|
||||
let mut users = user_vec_to_hashmap(string_to(&passwd_content));
|
||||
let groups = string_to(&group_content);
|
||||
let shadow_entries: Vec<crate::Shadow> = string_to(shadow_content);
|
||||
let mut users = user_vec_to_hashmap(string_to(passwd_content));
|
||||
let groups = string_to(group_content);
|
||||
shadow_to_users(&mut users, shadow_entries);
|
||||
let res = Self {
|
||||
Self {
|
||||
source_files: files::Files {
|
||||
passwd: None,
|
||||
group: None,
|
||||
@ -45,13 +38,11 @@ impl UserDBLocal {
|
||||
},
|
||||
users,
|
||||
groups,
|
||||
source_hashes: hashes::Hashes::new(&passwd_content, &shadow_content, &group_content),
|
||||
};
|
||||
res
|
||||
source_hashes: hashes::Hashes::new(passwd_content, shadow_content, group_content),
|
||||
}
|
||||
}
|
||||
|
||||
/// Import the database from a [`Files`] struct
|
||||
#[must_use]
|
||||
pub fn load_files(files: files::Files) -> Result<Self, crate::UserLibError> {
|
||||
// Get the Strings for the files use an inner block to drop references after read.
|
||||
let (my_passwd_lines, my_shadow_lines, my_group_lines) = {
|
||||
@ -77,10 +68,10 @@ impl UserDBLocal {
|
||||
}
|
||||
fn delete_from_passwd(
|
||||
user: &crate::User,
|
||||
passwd_file_content: String,
|
||||
passwd_file_content: &str,
|
||||
locked_p: &mut files::LockedFileGuard,
|
||||
) -> Result<(), UserLibError> {
|
||||
let modified_p = user.remove_in(&passwd_file_content);
|
||||
let modified_p = user.remove_in(passwd_file_content);
|
||||
|
||||
// write the new content to the file.
|
||||
let ncont = locked_p.replace_contents(modified_p);
|
||||
@ -92,13 +83,13 @@ impl UserDBLocal {
|
||||
|
||||
fn delete_from_shadow(
|
||||
user: &crate::User,
|
||||
shadow_file_content: String,
|
||||
shadow_file_content: &str,
|
||||
locked_s: &mut files::LockedFileGuard,
|
||||
) -> Result<(), UserLibError> {
|
||||
let shad = user.get_shadow();
|
||||
match shad {
|
||||
Some(shadow) => {
|
||||
let modified_s = shadow.remove_in(&shadow_file_content);
|
||||
let modified_s = shadow.remove_in(shadow_file_content);
|
||||
let ncont = locked_s.replace_contents(modified_s);
|
||||
match ncont {
|
||||
Ok(_) => Ok(()),
|
||||
@ -116,10 +107,10 @@ impl UserDBLocal {
|
||||
|
||||
fn delete_from_group(
|
||||
group: &crate::Group,
|
||||
group_file_content: String,
|
||||
group_file_content: &str,
|
||||
locked_g: &mut files::LockedFileGuard,
|
||||
) -> Result<(), UserLibError> {
|
||||
let modified_g = group.remove_in(&group_file_content);
|
||||
let modified_g = group.remove_in(group_file_content);
|
||||
let replace_result = locked_g.replace_contents(modified_g);
|
||||
match replace_result {
|
||||
Ok(_) => Ok(()),
|
||||
@ -133,17 +124,17 @@ impl UserDBLocal {
|
||||
}
|
||||
|
||||
fn delete_home(user: &crate::User) -> std::io::Result<()> {
|
||||
match user.get_home_dir() {
|
||||
Some(dir) => std::fs::remove_dir_all(dir),
|
||||
None => {
|
||||
error!("Failed to remove the home directory! As the user did not have one.");
|
||||
if let Some(dir) = user.get_home_dir() {
|
||||
std::fs::remove_dir_all(dir)
|
||||
} else {
|
||||
let error_msg = "Failed to remove the home directory! As the user did not have one.";
|
||||
error!("{}", error_msg);
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
"Failed to remove the home directory! As the user did not have one.",
|
||||
error_msg,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_group_pos_by_id(&self, id: u32) -> Option<(&crate::Group, usize)> {
|
||||
for (i, group) in self.groups.iter().enumerate() {
|
||||
@ -190,8 +181,8 @@ impl UserDBWrite for UserDBLocal {
|
||||
error!("The source files have changed. Deleting the user could corrupt the userdatabase. Aborting!");
|
||||
Err(format!("The userdatabase has been changed {}", args.username).into())
|
||||
} else {
|
||||
Self::delete_from_passwd(user, passwd_file_content, &mut locked_p)?;
|
||||
Self::delete_from_shadow(user, shadow_file_content, &mut locked_s)?;
|
||||
Self::delete_from_passwd(user, &passwd_file_content, &mut locked_p)?;
|
||||
Self::delete_from_shadow(user, &shadow_file_content, &mut locked_s)?;
|
||||
if args.delete_home == DeleteHome::Delete {
|
||||
Self::delete_home(user)?;
|
||||
}
|
||||
@ -206,7 +197,7 @@ impl UserDBWrite for UserDBLocal {
|
||||
{
|
||||
UserDBLocal::delete_from_group(
|
||||
group,
|
||||
group_file_content,
|
||||
&group_file_content,
|
||||
&mut locked_g,
|
||||
)?;
|
||||
let _gres = self.groups.remove(id);
|
||||
@ -297,9 +288,9 @@ impl UserDBRead for UserDBLocal {
|
||||
|
||||
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() {
|
||||
for user in self.users.values() {
|
||||
if user.get_uid() == uid {
|
||||
return Some(&user);
|
||||
return Some(user);
|
||||
}
|
||||
}
|
||||
None
|
||||
@ -310,7 +301,7 @@ impl UserDBRead for UserDBLocal {
|
||||
}
|
||||
|
||||
fn get_group_by_name(&self, name: &str) -> Option<&crate::Group> {
|
||||
for group in self.groups.iter() {
|
||||
for group in &self.groups {
|
||||
if group.get_groupname()? == name {
|
||||
return Some(group);
|
||||
}
|
||||
@ -319,7 +310,7 @@ impl UserDBRead for UserDBLocal {
|
||||
}
|
||||
|
||||
fn get_group_by_id(&self, id: u32) -> Option<&crate::Group> {
|
||||
for group in self.groups.iter() {
|
||||
for group in &self.groups {
|
||||
if group.get_gid()? == id {
|
||||
return Some(group);
|
||||
}
|
||||
@ -376,7 +367,7 @@ fn shadow_to_users(
|
||||
for pass in shadow {
|
||||
let user = users
|
||||
.get_mut(pass.get_username())
|
||||
.expect(&format!("the user {} does not exist", pass.get_username()));
|
||||
.unwrap_or_else(|| panic!("the user {} does not exist", pass.get_username()));
|
||||
user.password = crate::Password::Shadow(pass);
|
||||
}
|
||||
users
|
||||
@ -397,7 +388,7 @@ fn user_vec_to_hashmap(users: Vec<crate::User>) -> HashMap<String, crate::User>
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Try to parse a String into some Object
|
||||
/// Try to parse a String into some Object.
|
||||
///
|
||||
/// # Errors
|
||||
/// if the parsing failed a [`UserLibError::Message`](crate::userlib_error::UserLibError::Message) is returned containing a more detailed error message.
|
||||
@ -412,12 +403,20 @@ fn string_to<T>(source: &str) -> Vec<T>
|
||||
where
|
||||
T: NewFromString,
|
||||
{
|
||||
use std::convert::TryInto;
|
||||
source
|
||||
.lines()
|
||||
.enumerate()
|
||||
.filter_map(|(n, line)| {
|
||||
if line.len() > 5 {
|
||||
Some(T::new_from_string(line.to_owned(), n as u32).expect("failed to read lines"))
|
||||
Some(
|
||||
T::new_from_string(
|
||||
line.to_owned(),
|
||||
n.try_into()
|
||||
.unwrap_or_else(|e| panic!("Failed to convert usize to u32 {}", e)),
|
||||
)
|
||||
.expect("failed to read lines"),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -484,10 +483,10 @@ fn test_user_db_write_implementation() {
|
||||
|
||||
assert_eq!(data.get_all_users().len(), 1);
|
||||
assert!(data
|
||||
.delete_user(NewUserArgs::builder().username(&user).build().unwrap())
|
||||
.delete_user(NewUserArgs::builder().username(user).build().unwrap())
|
||||
.is_ok());
|
||||
assert!(data
|
||||
.delete_user(NewUserArgs::builder().username(&user).build().unwrap())
|
||||
.delete_user(NewUserArgs::builder().username(user).build().unwrap())
|
||||
.is_err());
|
||||
assert_eq!(data.get_all_users().len(), 0);
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ fn test_test() {
|
||||
|
||||
let mf = adduser::Files {
|
||||
passwd: Some(p.path.clone()),
|
||||
shadow: Some(s.path.clone()),
|
||||
group: Some(g.path.clone()),
|
||||
shadow: Some(s.path),
|
||||
group: Some(g.path),
|
||||
};
|
||||
|
||||
let mut db = adduser::UserDBLocal::load_files(mf).unwrap();
|
||||
@ -32,9 +32,9 @@ fn test_test() {
|
||||
);
|
||||
let pf2 = fs::read_to_string(&p.path).unwrap();
|
||||
assert_eq!(user_res.unwrap().get_username().unwrap(), "teste");
|
||||
let pfl = pf.lines();
|
||||
let pfl2 = pf2.lines();
|
||||
for (l1, l2) in pfl.zip(pfl2) {
|
||||
let pflines = pf.lines();
|
||||
let pflines2 = pf2.lines();
|
||||
for (l1, l2) in pflines.zip(pflines2) {
|
||||
if l1 != l2 {
|
||||
dbg!(l1, l2);
|
||||
assert!(l1.starts_with("teste"));
|
||||
|
@ -12,6 +12,7 @@ pub struct Fixture {
|
||||
}
|
||||
|
||||
impl Fixture {
|
||||
#[must_use]
|
||||
pub fn blank(fixture_filename: &str) -> Self {
|
||||
// First, figure out the right file in `tests/fixtures/`:
|
||||
let root_dir = &env::var("CARGO_MANIFEST_DIR").expect("$CARGO_MANIFEST_DIR");
|
||||
@ -24,14 +25,15 @@ impl Fixture {
|
||||
let mut path = PathBuf::from(&tempdir.path());
|
||||
path.push(&fixture_filename);
|
||||
|
||||
Fixture {
|
||||
Self {
|
||||
_tempdir: tempdir,
|
||||
source,
|
||||
path,
|
||||
}
|
||||
}
|
||||
#[must_use]
|
||||
pub fn copy(fixture_filename: &str) -> Self {
|
||||
let fixture = Fixture::blank(fixture_filename);
|
||||
let fixture = Self::blank(fixture_filename);
|
||||
fs::copy(&fixture.source, &fixture.path).unwrap();
|
||||
fixture
|
||||
}
|
||||
@ -41,6 +43,6 @@ impl Deref for Fixture {
|
||||
type Target = Path;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.path.deref()
|
||||
&self.path
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user