| use iggy::models::permissions::TopicPermissions; |
| use std::str::FromStr; |
| |
| use super::constants::{ |
| MANAGE_TOPIC_LONG, MANAGE_TOPIC_SHORT, POLL_MESSAGES_LONG, POLL_MESSAGES_SHORT, |
| READ_TOPIC_LONG, READ_TOPIC_SHORT, SEND_MESSAGES_LONG, SEND_MESSAGES_SHORT, |
| }; |
| |
| #[derive(Clone, Debug, PartialEq)] |
| enum TopicPermission { |
| ManageTopic, |
| ReadTopic, |
| PollMessages, |
| SendMessages, |
| } |
| |
| #[derive(Clone, Debug, PartialEq)] |
| pub(crate) struct TopicPermissionError(String); |
| |
| impl FromStr for TopicPermission { |
| type Err = TopicPermissionError; |
| |
| fn from_str(s: &str) -> Result<Self, Self::Err> { |
| match s { |
| MANAGE_TOPIC_SHORT | MANAGE_TOPIC_LONG => Ok(TopicPermission::ManageTopic), |
| READ_TOPIC_SHORT | READ_TOPIC_LONG => Ok(TopicPermission::ReadTopic), |
| POLL_MESSAGES_SHORT | POLL_MESSAGES_LONG => Ok(TopicPermission::PollMessages), |
| SEND_MESSAGES_SHORT | SEND_MESSAGES_LONG => Ok(TopicPermission::SendMessages), |
| "" => Err(TopicPermissionError("[empty]".to_owned())), |
| _ => Err(TopicPermissionError(s.to_owned())), |
| } |
| } |
| } |
| |
| #[derive(Clone, Debug, PartialEq)] |
| pub(crate) struct TopicPermissionsArg { |
| pub(crate) topic_id: u32, |
| pub(crate) permissions: TopicPermissions, |
| } |
| |
| impl From<TopicPermissionsArg> for TopicPermissions { |
| fn from(cmd: TopicPermissionsArg) -> Self { |
| cmd.permissions |
| } |
| } |
| |
| impl TopicPermissionsArg { |
| fn new(topic_id: u32, topic_permissions: Vec<TopicPermission>) -> Self { |
| let mut result = Self { |
| topic_id, |
| permissions: TopicPermissions::default(), |
| }; |
| |
| for permission in topic_permissions { |
| result.set_permission(permission); |
| } |
| |
| result |
| } |
| |
| fn set_permission(&mut self, permission: TopicPermission) { |
| match permission { |
| TopicPermission::ManageTopic => self.permissions.manage_topic = true, |
| TopicPermission::ReadTopic => self.permissions.read_topic = true, |
| TopicPermission::PollMessages => self.permissions.poll_messages = true, |
| TopicPermission::SendMessages => self.permissions.send_messages = true, |
| } |
| } |
| } |
| |
| impl FromStr for TopicPermissionsArg { |
| type Err = String; |
| |
| fn from_str(s: &str) -> Result<Self, Self::Err> { |
| let mut parts = s.split(':'); |
| let topic_id = parts |
| .next() |
| .ok_or("Missing topic ID".to_string()) |
| .and_then(|id| { |
| id.parse() |
| .map_err(|error| format!("Invalid topic ID - {}", error)) |
| })?; |
| |
| let permissions: Vec<TopicPermission> = match parts.next() { |
| Some(permissions_str) => { |
| let (values, errors): (Vec<_>, Vec<_>) = permissions_str |
| .split(',') |
| .map(|s| s.parse::<TopicPermission>()) |
| .partition(Result::is_ok); |
| |
| if !errors.is_empty() { |
| let errors = errors |
| .into_iter() |
| .map(|e| format!("\"{}\"", e.err().unwrap().0)) |
| .collect::<Vec<String>>(); |
| |
| return Err(format!( |
| "Unknown permission{} {} for topic ID: {}", |
| match errors.len() { |
| 1 => "", |
| _ => "s", |
| }, |
| errors.join(", "), |
| topic_id |
| )); |
| } |
| |
| values.into_iter().map(|p| p.unwrap()).collect() |
| } |
| None => vec![], |
| }; |
| |
| Ok(TopicPermissionsArg::new(topic_id, permissions)) |
| } |
| } |
| |
| #[cfg(test)] |
| mod tests { |
| use super::*; |
| |
| #[test] |
| fn should_deserialize_single_permission() { |
| assert_eq!( |
| TopicPermission::from_str("manage_topic").unwrap(), |
| TopicPermission::ManageTopic |
| ); |
| assert_eq!( |
| TopicPermission::from_str("read_topic").unwrap(), |
| TopicPermission::ReadTopic |
| ); |
| assert_eq!( |
| TopicPermission::from_str("poll_messages").unwrap(), |
| TopicPermission::PollMessages |
| ); |
| assert_eq!( |
| TopicPermission::from_str("send_messages").unwrap(), |
| TopicPermission::SendMessages |
| ); |
| } |
| |
| #[test] |
| fn should_deserialize_single_short_permission() { |
| assert_eq!( |
| TopicPermission::from_str("m_top").unwrap(), |
| TopicPermission::ManageTopic |
| ); |
| assert_eq!( |
| TopicPermission::from_str("r_top").unwrap(), |
| TopicPermission::ReadTopic |
| ); |
| assert_eq!( |
| TopicPermission::from_str("p_msg").unwrap(), |
| TopicPermission::PollMessages |
| ); |
| assert_eq!( |
| TopicPermission::from_str("s_msg").unwrap(), |
| TopicPermission::SendMessages |
| ); |
| } |
| |
| #[test] |
| fn should_not_deserialize_single_permission() { |
| let wrong_permission = TopicPermission::from_str("rad_topic"); |
| assert!(wrong_permission.is_err()); |
| assert_eq!( |
| wrong_permission.unwrap_err(), |
| TopicPermissionError("rad_topic".to_owned()) |
| ); |
| let empty_permission = TopicPermission::from_str(""); |
| assert!(empty_permission.is_err()); |
| assert_eq!( |
| empty_permission.unwrap_err(), |
| TopicPermissionError("[empty]".to_owned()) |
| ); |
| } |
| |
| #[test] |
| fn should_not_deserialize_single_short_permission() { |
| let wrong_permission = TopicPermission::from_str("w_top"); |
| assert!(wrong_permission.is_err()); |
| assert_eq!( |
| wrong_permission.unwrap_err(), |
| TopicPermissionError("w_top".to_owned()) |
| ); |
| let wrong_permission = TopicPermission::from_str("p_top"); |
| assert!(wrong_permission.is_err()); |
| assert_eq!( |
| wrong_permission.unwrap_err(), |
| TopicPermissionError("p_top".to_owned()) |
| ); |
| } |
| |
| #[test] |
| fn should_deserialize_permissions() { |
| assert_eq!( |
| TopicPermissionsArg::from_str("1:manage_topic,read_topic,poll_messages,send_messages") |
| .unwrap(), |
| TopicPermissionsArg { |
| topic_id: 1, |
| permissions: TopicPermissions { |
| manage_topic: true, |
| read_topic: true, |
| poll_messages: true, |
| send_messages: true, |
| } |
| } |
| ); |
| assert_eq!( |
| TopicPermissionsArg::from_str("1:manage_topic,read_topic").unwrap(), |
| TopicPermissionsArg { |
| topic_id: 1, |
| permissions: TopicPermissions { |
| manage_topic: true, |
| read_topic: true, |
| poll_messages: false, |
| send_messages: false, |
| } |
| } |
| ); |
| assert_eq!( |
| TopicPermissionsArg::from_str("52:send_messages,read_topic").unwrap(), |
| TopicPermissionsArg { |
| topic_id: 52, |
| permissions: TopicPermissions { |
| manage_topic: false, |
| read_topic: true, |
| poll_messages: false, |
| send_messages: true, |
| } |
| } |
| ); |
| assert_eq!( |
| TopicPermissionsArg::from_str("66").unwrap(), |
| TopicPermissionsArg { |
| topic_id: 66, |
| permissions: TopicPermissions { |
| manage_topic: false, |
| read_topic: false, |
| poll_messages: false, |
| send_messages: false, |
| } |
| } |
| ); |
| assert_eq!( |
| TopicPermissionsArg::from_str("3:send_messages").unwrap(), |
| TopicPermissionsArg { |
| topic_id: 3, |
| permissions: TopicPermissions { |
| manage_topic: false, |
| read_topic: false, |
| poll_messages: false, |
| send_messages: true, |
| } |
| } |
| ); |
| } |
| |
| #[test] |
| fn should_deserialize_short_permissions() { |
| assert_eq!( |
| TopicPermissionsArg::from_str("4:m_top,r_top,p_msg,s_msg").unwrap(), |
| TopicPermissionsArg { |
| topic_id: 4, |
| permissions: TopicPermissions { |
| manage_topic: true, |
| read_topic: true, |
| poll_messages: true, |
| send_messages: true, |
| } |
| } |
| ); |
| assert_eq!( |
| TopicPermissionsArg::from_str("2:m_top,r_top").unwrap(), |
| TopicPermissionsArg { |
| topic_id: 2, |
| permissions: TopicPermissions { |
| manage_topic: true, |
| read_topic: true, |
| poll_messages: false, |
| send_messages: false, |
| } |
| } |
| ); |
| assert_eq!( |
| TopicPermissionsArg::from_str("41:s_msg,r_top").unwrap(), |
| TopicPermissionsArg { |
| topic_id: 41, |
| permissions: TopicPermissions { |
| manage_topic: false, |
| read_topic: true, |
| poll_messages: false, |
| send_messages: true, |
| } |
| } |
| ); |
| assert_eq!( |
| TopicPermissionsArg::from_str("99:s_msg").unwrap(), |
| TopicPermissionsArg { |
| topic_id: 99, |
| permissions: TopicPermissions { |
| manage_topic: false, |
| read_topic: false, |
| poll_messages: false, |
| send_messages: true, |
| } |
| } |
| ); |
| } |
| |
| #[test] |
| fn should_not_deserialize_permissions() { |
| let wrong_id = TopicPermissionsArg::from_str("4a"); |
| assert!(wrong_id.is_err()); |
| assert_eq!( |
| wrong_id.unwrap_err(), |
| "Invalid topic ID - invalid digit found in string" |
| ); |
| let wrong_permission = TopicPermissionsArg::from_str("41:reed_topic"); |
| assert!(wrong_permission.is_err()); |
| assert_eq!( |
| wrong_permission.unwrap_err(), |
| "Unknown permission \"reed_topic\" for topic ID: 41" |
| ); |
| let multiple_wrong = TopicPermissionsArg::from_str("56:reed_topic,sent_messages"); |
| assert!(multiple_wrong.is_err()); |
| assert_eq!( |
| multiple_wrong.unwrap_err(), |
| "Unknown permissions \"reed_topic\", \"sent_messages\" for topic ID: 56" |
| ); |
| } |
| |
| #[test] |
| fn should_not_deserialize_short_permissions() { |
| let wrong_permission = TopicPermissionsArg::from_str("4:r_topic"); |
| assert!(wrong_permission.is_err()); |
| assert_eq!( |
| wrong_permission.unwrap_err(), |
| "Unknown permission \"r_topic\" for topic ID: 4" |
| ); |
| let multiple_wrong = TopicPermissionsArg::from_str("55:r_topic,sent_msg"); |
| assert!(multiple_wrong.is_err()); |
| assert_eq!( |
| multiple_wrong.unwrap_err(), |
| "Unknown permissions \"r_topic\", \"sent_msg\" for topic ID: 55" |
| ); |
| } |
| } |