From a9b8f7cee75bdafbf490e8c5b1ee6ed81e0ae393 Mon Sep 17 00:00:00 2001 From: h7x4 Date: Wed, 7 Aug 2024 17:14:24 +0200 Subject: [PATCH] user_operations: don't fetch auth_string/password, only check existence --- .../mysql_useradm.rs | 28 +++++++------ src/cli/user_command.rs | 2 +- src/core/user_operations.rs | 40 +++++-------------- 3 files changed, 26 insertions(+), 44 deletions(-) diff --git a/src/cli/mysql_admutils_compatibility/mysql_useradm.rs b/src/cli/mysql_admutils_compatibility/mysql_useradm.rs index f8893c6..d6ea066 100644 --- a/src/cli/mysql_admutils_compatibility/mysql_useradm.rs +++ b/src/cli/mysql_admutils_compatibility/mysql_useradm.rs @@ -11,7 +11,7 @@ use crate::{ config::{get_config, mysql_connection_from_config, GlobalConfigArgs}, user_operations::{ create_database_user, delete_database_user, get_all_database_users_for_unix_user, - password_is_set_for_database_user, set_password_for_database_user, user_exists, + get_database_user_for_user, set_password_for_database_user, user_exists, }, }, }; @@ -150,22 +150,24 @@ async fn passwd(args: PasswdArgs, connection: &mut MySqlConnection) -> anyhow::R async fn show(args: ShowArgs, connection: &mut MySqlConnection) -> anyhow::Result<()> { let users = if args.name.is_empty() { let unix_user = get_current_unix_user()?; - get_all_database_users_for_unix_user(&unix_user, connection) - .await? - .into_iter() - .map(|u| u.user) - .collect() + get_all_database_users_for_unix_user(&unix_user, connection).await? } else { - filter_db_or_user_names(args.name, DbOrUser::User)? + let filtered_usernames = filter_db_or_user_names(args.name, DbOrUser::User)?; + let mut result = Vec::with_capacity(filtered_usernames.len()); + for username in filtered_usernames.iter() { + // TODO: fetch all users in one query + get_database_user_for_user(username, connection) + .await? + .map(|user| result.push(user)); + } + result }; for user in users { - let password_is_set = password_is_set_for_database_user(&user, connection).await?; - - match password_is_set { - Some(true) => println!("User '{}': password set.", user), - Some(false) => println!("User '{}': no password set.", user), - None => {} + if user.has_password { + println!("User '{}': password set.", user.user); + } else { + println!("User '{}': no password set.", user.user); } } diff --git a/src/cli/user_command.rs b/src/cli/user_command.rs index 6d86489..3579ec8 100644 --- a/src/cli/user_command.rs +++ b/src/cli/user_command.rs @@ -197,7 +197,7 @@ async fn show_users(args: UserShowArgs, conn: &mut MySqlConnection) -> anyhow::R println!( "User '{}': {}", &user.user, - if !(user.authentication_string.is_empty() && user.password.is_empty()) { + if user.has_password { "password set." } else { "no password set." diff --git a/src/core/user_operations.rs b/src/core/user_operations.rs index 125f77d..8059c76 100644 --- a/src/core/user_operations.rs +++ b/src/core/user_operations.rs @@ -93,30 +93,6 @@ pub async fn set_password_for_database_user( Ok(()) } -/// Helper struct to deserialize the query made in `password_is_set_for_database_user`. -#[derive(sqlx::FromRow)] -#[sqlx(transparent)] -struct PasswordIsSet(bool); - -/// This function checks if a database user has a password set. -/// It returns `Ok(None)` if the user does not exist. -pub async fn password_is_set_for_database_user( - db_user: &str, - conn: &mut MySqlConnection, -) -> anyhow::Result> { - let unix_user = crate::core::common::get_current_unix_user()?; - validate_user_name(db_user, &unix_user)?; - - let user_has_password = sqlx::query_as::<_, PasswordIsSet>( - "SELECT authentication_string != '' FROM mysql.user WHERE User = ?", - ) - .bind(db_user) - .fetch_optional(conn) - .await?; - - Ok(user_has_password.map(|PasswordIsSet(is_set)| is_set)) -} - /// This struct contains information about a database user. /// This can be extended if we need more information in the future. #[derive(Debug, Clone, FromRow, Serialize, Deserialize)] @@ -127,10 +103,8 @@ pub struct DatabaseUser { #[sqlx(rename = "Host")] pub host: String, - #[sqlx(rename = "Password")] - pub password: String, - - pub authentication_string: String, + #[sqlx(rename = "`Password` != '' OR `authentication_string` != ''")] + pub has_password: bool, } /// This function fetches all database users that have a prefix matching the @@ -141,7 +115,10 @@ pub async fn get_all_database_users_for_unix_user( ) -> anyhow::Result> { let users = sqlx::query_as::<_, DatabaseUser>( r#" - SELECT `User`, `Host`, `Password`, `authentication_string` + SELECT + `User`, + `Host`, + `Password` != '' OR `authentication_string` != '' FROM `mysql`.`user` WHERE `User` REGEXP ? "#, @@ -160,7 +137,10 @@ pub async fn get_database_user_for_user( ) -> anyhow::Result> { let user = sqlx::query_as::<_, DatabaseUser>( r#" - SELECT `User`, `Host`, `Password`, `authentication_string` + SELECT + `User`, + `Host`, + `Password` != '' OR `authentication_string` != '' FROM `mysql`.`user` WHERE `User` = ? "#,