Compare commits
	
		
			2 Commits
		
	
	
		
			676a5218e6
			...
			1ab0adbc06
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 1ab0adbc06 | |||
| 5000fba6e7 | 
							
								
								
									
										52
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										52
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							| @ -3,3 +3,55 @@ | |||||||
| [[package]] | [[package]] | ||||||
| name = "adduser" | name = "adduser" | ||||||
| version = "0.1.0" | version = "0.1.0" | ||||||
|  | dependencies = [ | ||||||
|  |  "lazy_static", | ||||||
|  |  "regex", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "aho-corasick" | ||||||
|  | version = "0.7.13" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" | ||||||
|  | dependencies = [ | ||||||
|  |  "memchr", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "lazy_static" | ||||||
|  | version = "1.4.0" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "memchr" | ||||||
|  | version = "2.3.3" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "regex" | ||||||
|  | version = "1.3.9" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" | ||||||
|  | dependencies = [ | ||||||
|  |  "aho-corasick", | ||||||
|  |  "memchr", | ||||||
|  |  "regex-syntax", | ||||||
|  |  "thread_local", | ||||||
|  | ] | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "regex-syntax" | ||||||
|  | version = "0.6.18" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" | ||||||
|  | 
 | ||||||
|  | [[package]] | ||||||
|  | name = "thread_local" | ||||||
|  | version = "1.0.1" | ||||||
|  | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||||
|  | checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" | ||||||
|  | dependencies = [ | ||||||
|  |  "lazy_static", | ||||||
|  | ] | ||||||
|  | |||||||
| @ -7,3 +7,5 @@ edition = "2018" | |||||||
| # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||||||
| 
 | 
 | ||||||
| [dependencies] | [dependencies] | ||||||
|  | regex = "1" | ||||||
|  | lazy_static = "1.4" | ||||||
|  | |||||||
| @ -1,3 +1,6 @@ | |||||||
|  | #[macro_use] | ||||||
|  | extern crate lazy_static; | ||||||
|  | 
 | ||||||
| pub mod passwd; | pub mod passwd; | ||||||
| pub mod userlib_error; | pub mod userlib_error; | ||||||
| pub use passwd::{Password, Username}; | pub use passwd::{Password, Username}; | ||||||
|  | |||||||
| @ -7,6 +7,8 @@ | |||||||
| )] | )] | ||||||
| #![allow(clippy::non_ascii_literal)] | #![allow(clippy::non_ascii_literal)] | ||||||
| 
 | 
 | ||||||
|  | use regex::Regex; | ||||||
|  | 
 | ||||||
| use crate::userlib_error::UserLibError; | use crate::userlib_error::UserLibError; | ||||||
| use std::cmp::Eq; | use std::cmp::Eq; | ||||||
| use std::convert::TryFrom; | use std::convert::TryFrom; | ||||||
| @ -37,7 +39,12 @@ pub struct Uid { | |||||||
| pub struct Gid { | pub struct Gid { | ||||||
|     gid: u32, |     gid: u32, | ||||||
| } | } | ||||||
| 
 | /// The gecos field of a user.
 | ||||||
|  | ///
 | ||||||
|  | /// In the `/etc/passwd` file this field is a `,` sepparated list of items.
 | ||||||
|  | /// The first 4 values are more or less standardised to be full name, room, phone at work and phone at home. After that there can be some extra fields often containing the emailadress and even additional information.
 | ||||||
|  | ///
 | ||||||
|  | /// This enum represents the first 4 values by name and adds the other values to a list of strings [`Gecos::Detail`]. If only one field is found and no `,` at all this value is used as a human readable comment [`Gecos::Simple`].
 | ||||||
| #[derive(Debug, PartialEq, Eq)] | #[derive(Debug, PartialEq, Eq)] | ||||||
| pub enum Gecos<'a> { | pub enum Gecos<'a> { | ||||||
|     Detail { |     Detail { | ||||||
| @ -254,7 +261,15 @@ impl Display for Username<'_> { | |||||||
| impl<'a> TryFrom<&'a str> for Username<'a> { | impl<'a> TryFrom<&'a str> for Username<'a> { | ||||||
|     type Error = UserLibError; |     type Error = UserLibError; | ||||||
|     fn try_from(source: &'a str) -> std::result::Result<Self, Self::Error> { |     fn try_from(source: &'a str) -> std::result::Result<Self, Self::Error> { | ||||||
|         Ok(Self { username: source }) |         lazy_static! { | ||||||
|  |             static ref USERVALIDATION: Regex = | ||||||
|  |                 Regex::new("^[a-z_]([a-z0-9_-]{0,31}|[a-z0-9_-]{0,30}\\$)$").unwrap(); | ||||||
|  |         } | ||||||
|  |         if USERVALIDATION.is_match(source) { | ||||||
|  |             Ok(Self { username: source }) | ||||||
|  |         } else { | ||||||
|  |             Err(UserLibError::Message("Invalid username".into())) | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -381,6 +396,37 @@ impl<'a> TryFrom<&'a str> for ShellPath<'a> { | |||||||
| 
 | 
 | ||||||
| // Tests ----------------------------------------------------------------------
 | // Tests ----------------------------------------------------------------------
 | ||||||
| 
 | 
 | ||||||
|  | #[test] | ||||||
|  | fn test_username_validation() { | ||||||
|  |     // Failing tests
 | ||||||
|  |     let umlauts = Username::try_from("täst"); // umlauts
 | ||||||
|  |     assert_eq!( | ||||||
|  |         Err(UserLibError::Message("Invalid username".into())), | ||||||
|  |         umlauts | ||||||
|  |     ); | ||||||
|  |     let number_first = Username::try_from("11elf"); // numbers first
 | ||||||
|  |     assert_eq!( | ||||||
|  |         Err(UserLibError::Message("Invalid username".into())), | ||||||
|  |         number_first | ||||||
|  |     ); | ||||||
|  |     let slashes = Username::try_from("test/name"); // slashes in the name
 | ||||||
|  |     assert_eq!( | ||||||
|  |         Err(UserLibError::Message("Invalid username".into())), | ||||||
|  |         slashes | ||||||
|  |     ); | ||||||
|  |     let long = Username::try_from("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); // maximum size 32 letters
 | ||||||
|  |     assert_eq!(Err(UserLibError::Message("Invalid username".into())), long); | ||||||
|  |     // Working tests
 | ||||||
|  |     let single = Username::try_from("t"); // single characters are ok
 | ||||||
|  |     assert_eq!(single.unwrap().username, "t"); | ||||||
|  |     let normal = Username::try_from("superman"); // regular username
 | ||||||
|  |     assert_eq!(normal.unwrap().username, "superman"); | ||||||
|  |     let normal = Username::try_from("anna3pete"); // regular username containing a number
 | ||||||
|  |     assert_eq!(normal.unwrap().username, "anna3pete"); | ||||||
|  |     let normal = Username::try_from("enya$"); // regular username ending in a $
 | ||||||
|  |     assert_eq!(normal.unwrap().username, "enya$"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| #[test] | #[test] | ||||||
| fn test_default_user() { | fn test_default_user() { | ||||||
|     // Check if a user can be created.
 |     // Check if a user can be created.
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user