Misc 3 #57
|
@ -290,14 +290,14 @@ async fn show_users(
|
||||||
"User",
|
"User",
|
||||||
"Password is set",
|
"Password is set",
|
||||||
"Locked",
|
"Locked",
|
||||||
// "Databases where user has privileges"
|
"Databases where user has privileges"
|
||||||
]);
|
]);
|
||||||
for user in users {
|
for user in users {
|
||||||
table.add_row(row![
|
table.add_row(row![
|
||||||
user.user,
|
user.user,
|
||||||
user.has_password,
|
user.has_password,
|
||||||
user.is_locked,
|
user.is_locked,
|
||||||
// user.databases.join("\n")
|
user.databases.join("\n")
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
table.printstd();
|
table.printstd();
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
use itertools::Itertools;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
use indoc::formatdoc;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -20,6 +22,8 @@ use crate::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::database_privilege_operations::DATABASE_PRIVILEGE_FIELDS;
|
||||||
|
|
||||||
// NOTE: this function is unsafe because it does no input validation.
|
// NOTE: this function is unsafe because it does no input validation.
|
||||||
async fn unsafe_user_exists(
|
async fn unsafe_user_exists(
|
||||||
db_user: &str,
|
db_user: &str,
|
||||||
|
@ -309,6 +313,9 @@ pub struct DatabaseUser {
|
||||||
|
|
||||||
#[sqlx(rename = "is_locked")]
|
#[sqlx(rename = "is_locked")]
|
||||||
pub is_locked: bool,
|
pub is_locked: bool,
|
||||||
|
|
||||||
|
#[sqlx(skip)]
|
||||||
|
pub databases: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
const DB_USER_SELECT_STATEMENT: &str = r#"
|
const DB_USER_SELECT_STATEMENT: &str = r#"
|
||||||
|
@ -344,13 +351,17 @@ pub async fn list_database_users(
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = sqlx::query_as::<_, DatabaseUser>(
|
let mut result = sqlx::query_as::<_, DatabaseUser>(
|
||||||
&(DB_USER_SELECT_STATEMENT.to_string() + "WHERE `mysql`.`user`.`User` = ?"),
|
&(DB_USER_SELECT_STATEMENT.to_string() + "WHERE `mysql`.`user`.`User` = ?"),
|
||||||
)
|
)
|
||||||
.bind(&db_user)
|
.bind(&db_user)
|
||||||
.fetch_optional(&mut *connection)
|
.fetch_optional(&mut *connection)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
if let Ok(Some(user)) = result.as_mut() {
|
||||||
|
append_databases_where_user_has_privileges(user, &mut *connection).await;
|
||||||
|
}
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(Some(user)) => results.insert(db_user, Ok(user)),
|
Ok(Some(user)) => results.insert(db_user, Ok(user)),
|
||||||
Ok(None) => results.insert(db_user, Err(ListUsersError::UserDoesNotExist)),
|
Ok(None) => results.insert(db_user, Err(ListUsersError::UserDoesNotExist)),
|
||||||
|
@ -365,11 +376,50 @@ pub async fn list_all_database_users_for_unix_user(
|
||||||
unix_user: &UnixUser,
|
unix_user: &UnixUser,
|
||||||
connection: &mut MySqlConnection,
|
connection: &mut MySqlConnection,
|
||||||
) -> ListAllUsersOutput {
|
) -> ListAllUsersOutput {
|
||||||
sqlx::query_as::<_, DatabaseUser>(
|
let mut result = sqlx::query_as::<_, DatabaseUser>(
|
||||||
&(DB_USER_SELECT_STATEMENT.to_string() + "WHERE `mysql`.`user`.`User` REGEXP ?"),
|
&(DB_USER_SELECT_STATEMENT.to_string() + "WHERE `mysql`.`user`.`User` REGEXP ?"),
|
||||||
)
|
)
|
||||||
.bind(create_user_group_matching_regex(unix_user))
|
.bind(create_user_group_matching_regex(unix_user))
|
||||||
.fetch_all(connection)
|
.fetch_all(&mut *connection)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| ListAllUsersError::MySqlError(err.to_string()))
|
.map_err(|err| ListAllUsersError::MySqlError(err.to_string()));
|
||||||
|
|
||||||
|
if let Ok(users) = result.as_mut() {
|
||||||
|
for user in users {
|
||||||
|
append_databases_where_user_has_privileges(user, &mut *connection).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn append_databases_where_user_has_privileges(
|
||||||
|
database_user: &mut DatabaseUser,
|
||||||
|
connection: &mut MySqlConnection,
|
||||||
|
) {
|
||||||
|
let database_list = sqlx::query(
|
||||||
|
formatdoc!(
|
||||||
|
r#"
|
||||||
|
SELECT `db` AS `database`
|
||||||
|
FROM `db`
|
||||||
|
WHERE `user` = ? AND ({})
|
||||||
|
"#,
|
||||||
|
DATABASE_PRIVILEGE_FIELDS
|
||||||
|
.iter()
|
||||||
|
.map(|field| format!("`{}` = 'Y'", field))
|
||||||
|
.join(" OR "),
|
||||||
|
)
|
||||||
|
.as_str(),
|
||||||
|
)
|
||||||
|
.bind(database_user.user.clone())
|
||||||
|
.fetch_all(&mut *connection)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
database_user.databases = database_list
|
||||||
|
.map(|rows| {
|
||||||
|
rows.into_iter()
|
||||||
|
.map(|row| row.get::<String, _>("database"))
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue