| use crate::cli::common::{ |
| IggyCmdCommand, IggyCmdTest, IggyCmdTestCase, TestHelpCmd, TestUserId, CLAP_INDENT, |
| USAGE_PREFIX, |
| }; |
| use ahash::AHashMap; |
| use assert_cmd::assert::Assert; |
| use async_trait::async_trait; |
| use iggy::client::Client; |
| use iggy::models::permissions::{Permissions, StreamPermissions, TopicPermissions}; |
| use iggy::models::user_info::UserId; |
| use iggy::models::user_status::UserStatus; |
| use predicates::str::{is_match, starts_with}; |
| use serial_test::parallel; |
| |
| enum TestUser<'a> { |
| Existing(&'a str), |
| New(&'a str), |
| NewWithGlobalPerms(&'a str), |
| NewWithStreamPerms(&'a str, u32), |
| NewWithStreamAndTopicPerms(&'a str, u32, u32), |
| } |
| |
| struct TestUserGetCmd { |
| username: String, |
| status: UserStatus, |
| user_id: Option<UserId>, |
| using_user_id: TestUserId, |
| create_user: bool, |
| check_global_perms: bool, |
| check_stream_perms: Option<u32>, |
| check_topic_perms: Option<u32>, |
| } |
| |
| impl TestUserGetCmd { |
| fn new(test_user: TestUser, status: UserStatus, using_user_id: TestUserId) -> Self { |
| let (username, create_user, check_global_perms, check_stream_perms, check_topic_perms) = |
| match test_user { |
| TestUser::Existing(username) => (username.into(), false, true, None, None), |
| TestUser::New(username) => (username.into(), true, false, None, None), |
| TestUser::NewWithGlobalPerms(username) => (username.into(), true, true, None, None), |
| TestUser::NewWithStreamPerms(username, stream_id) => { |
| (username.into(), true, true, Some(stream_id), None) |
| } |
| TestUser::NewWithStreamAndTopicPerms(username, stream_id, topic_id) => { |
| (username.into(), true, true, Some(stream_id), Some(topic_id)) |
| } |
| }; |
| |
| Self { |
| username, |
| status, |
| user_id: None, |
| using_user_id, |
| create_user, |
| check_global_perms, |
| check_stream_perms, |
| check_topic_perms, |
| } |
| } |
| |
| fn get_user_id(&self) -> String { |
| match self.using_user_id { |
| TestUserId::Named => self.username.clone(), |
| TestUserId::Numeric => format!("{}", self.user_id.unwrap()), |
| } |
| } |
| |
| fn get_permissions(&self) -> Option<Permissions> { |
| if self.check_global_perms { |
| let mut permissions = Permissions::default(); |
| |
| if let Some(stream_id) = self.check_stream_perms { |
| let mut stream_perms = StreamPermissions::default(); |
| |
| if let Some(topic_id) = self.check_topic_perms { |
| stream_perms.topics = |
| Some(AHashMap::from([(topic_id, TopicPermissions::default())])); |
| }; |
| |
| permissions.streams = Some(AHashMap::from([(stream_id, stream_perms)])); |
| } |
| |
| Some(permissions) |
| } else { |
| None |
| } |
| } |
| } |
| |
| #[async_trait] |
| impl IggyCmdTestCase for TestUserGetCmd { |
| async fn prepare_server_state(&mut self, client: &dyn Client) { |
| if self.create_user { |
| let create_user = client |
| .create_user( |
| &self.username, |
| "secret", |
| self.status, |
| self.get_permissions(), |
| ) |
| .await; |
| assert!(create_user.is_ok()); |
| } |
| let user = client |
| .get_user(&self.username.as_str().try_into().unwrap()) |
| .await; |
| assert!(user.is_ok()); |
| let user = user.unwrap().expect("Failed to get user"); |
| self.user_id = Some(user.id); |
| } |
| |
| fn get_command(&self) -> IggyCmdCommand { |
| IggyCmdCommand::new() |
| .arg("user") |
| .arg("get") |
| .arg(self.get_user_id()) |
| .with_env_credentials() |
| } |
| |
| fn verify_command(&self, command_state: Assert) { |
| let user_id = self.get_user_id(); |
| |
| let assert = command_state |
| .success() |
| .stdout(starts_with(format!( |
| "Executing get user with ID: {}", |
| user_id |
| ))) |
| .stdout(is_match(format!("| Username[ ]+| {}", self.username)).unwrap()) |
| .stdout(is_match(format!("| Status[ ]+| {}", self.status)).unwrap()); |
| |
| // Check global permissions |
| let assert = if self.check_global_perms { |
| assert.stdout(is_match("Global[ ]+|[ ]+Permission[ ]+| Value").unwrap()) |
| } else { |
| assert |
| }; |
| |
| // Check stream permissions |
| let assert = if let Some(stream_id) = self.check_stream_perms { |
| assert.stdout( |
| is_match(format!( |
| "Stream: {}[ ]+|[ ]+Permission[ ]+| Value", |
| stream_id |
| )) |
| .unwrap(), |
| ) |
| } else { |
| assert |
| }; |
| |
| // Check topic permissions |
| if let Some(topic_id) = self.check_topic_perms { |
| assert.stdout( |
| is_match(format!("Topic: {}[ ]+|[ ]+Permission[ ]+| Value", topic_id)).unwrap(), |
| ); |
| } |
| } |
| |
| async fn verify_server_state(&self, client: &dyn Client) { |
| if self.create_user { |
| let deleted = client |
| .delete_user(&self.username.as_str().try_into().unwrap()) |
| .await; |
| assert!(deleted.is_ok()); |
| } |
| } |
| } |
| |
| #[tokio::test] |
| #[parallel] |
| pub async fn should_be_successful() { |
| let mut iggy_cmd_test = IggyCmdTest::default(); |
| |
| iggy_cmd_test.setup().await; |
| iggy_cmd_test |
| .execute_test(TestUserGetCmd::new( |
| TestUser::New("producer"), |
| UserStatus::Active, |
| TestUserId::Named, |
| )) |
| .await; |
| iggy_cmd_test |
| .execute_test(TestUserGetCmd::new( |
| TestUser::New("testing"), |
| UserStatus::Inactive, |
| TestUserId::Named, |
| )) |
| .await; |
| iggy_cmd_test |
| .execute_test(TestUserGetCmd::new( |
| TestUser::NewWithGlobalPerms("misc"), |
| UserStatus::Active, |
| TestUserId::Numeric, |
| )) |
| .await; |
| iggy_cmd_test |
| .execute_test(TestUserGetCmd::new( |
| TestUser::NewWithStreamPerms("tools", 3), |
| UserStatus::Active, |
| TestUserId::Named, |
| )) |
| .await; |
| iggy_cmd_test |
| .execute_test(TestUserGetCmd::new( |
| TestUser::NewWithStreamAndTopicPerms("limited", 1, 3), |
| UserStatus::Active, |
| TestUserId::Named, |
| )) |
| .await; |
| iggy_cmd_test |
| .execute_test(TestUserGetCmd::new( |
| TestUser::Existing("iggy"), |
| UserStatus::Active, |
| TestUserId::Numeric, |
| )) |
| .await; |
| iggy_cmd_test |
| .execute_test(TestUserGetCmd::new( |
| TestUser::Existing("iggy"), |
| UserStatus::Active, |
| TestUserId::Named, |
| )) |
| .await; |
| } |
| |
| #[tokio::test] |
| #[parallel] |
| pub async fn should_help_match() { |
| let mut iggy_cmd_test = IggyCmdTest::help_message(); |
| |
| iggy_cmd_test |
| .execute_test_for_help_command(TestHelpCmd::new( |
| vec!["user", "get", "--help"], |
| format!( |
| r#"Get details of a single user with given ID |
| |
| The user ID can be specified as either a username or an ID |
| |
| Examples: |
| iggy user get 2 |
| iggy user get testuser |
| |
| {USAGE_PREFIX} user get <USER_ID> |
| |
| Arguments: |
| <USER_ID> |
| User ID to get |
| {CLAP_INDENT} |
| The user ID can be specified as either a username or an ID |
| |
| Options: |
| -h, --help |
| Print help (see a summary with '-h') |
| "#, |
| ), |
| )) |
| .await; |
| } |
| |
| #[tokio::test] |
| #[parallel] |
| pub async fn should_short_help_match() { |
| let mut iggy_cmd_test = IggyCmdTest::default(); |
| |
| iggy_cmd_test |
| .execute_test_for_help_command(TestHelpCmd::new( |
| vec!["user", "get", "-h"], |
| format!( |
| r#"Get details of a single user with given ID |
| |
| {USAGE_PREFIX} user get <USER_ID> |
| |
| Arguments: |
| <USER_ID> User ID to get |
| |
| Options: |
| -h, --help Print help (see more with '--help') |
| "#, |
| ), |
| )) |
| .await; |
| } |