use crate::core::{common::UnixUser, protocol::request_validation::GroupDenylist}; use nix::unistd::Group; use sqlx::prelude::*; /// This function retrieves the groups of a user, filtering out any groups /// that are present in the provided denylist. pub fn get_user_filtered_groups(user: &UnixUser, group_denylist: &GroupDenylist) -> Vec { user.groups .iter() .cloned() .filter_map(|group_name| { match Group::from_name(&group_name) { Ok(Some(group)) => { if group_denylist.contains(&group.gid.as_raw()) { None } else { Some(group.name) } } // NOTE: allow non-existing groups to pass through the filter _ => Some(group_name), } }) .collect() } /// This function creates a regex that matches items (users, databases) /// that belong to the user or any of the user's groups. pub fn create_user_group_matching_regex(user: &UnixUser, group_denylist: &GroupDenylist) -> String { let filtered_groups = get_user_filtered_groups(user, group_denylist); if filtered_groups.is_empty() { format!("{}_.+", user.username) } else { format!("({}|{})_.+", user.username, filtered_groups.join("|")) } } /// Some mysql versions with some collations mark some columns as binary fields, /// which in the current version of sqlx is not parsable as string. /// See: #[inline] pub fn try_get_with_binary_fallback( row: &sqlx::mysql::MySqlRow, column: &str, ) -> Result { row.try_get(column).or_else(|_| { row.try_get::, _>(column) .map(|v| String::from_utf8_lossy(&v).to_string()) }) } #[cfg(test)] mod tests { use super::*; use regex::Regex; #[test] fn test_create_user_group_matching_regex() { let user = UnixUser { username: "user".to_owned(), groups: vec!["group1".to_owned(), "group2".to_owned()], }; let regex = create_user_group_matching_regex(&user, &GroupDenylist::new()); println!("Generated regex: {}", regex); let re = Regex::new(®ex).unwrap(); assert!(re.is_match("user_something")); assert!(re.is_match("group1_something")); assert!(re.is_match("group2_something")); assert!(!re.is_match("other_something")); assert!(!re.is_match("user")); assert!(!re.is_match("usersomething")); } }