parent
f43499fca0
commit
20669569f3
|
@ -14,8 +14,8 @@ use crate::server::sql::database_privilege_operations::{
|
||||||
|
|
||||||
pub fn db_priv_field_human_readable_name(name: &str) -> String {
|
pub fn db_priv_field_human_readable_name(name: &str) -> String {
|
||||||
match name {
|
match name {
|
||||||
"db" => "Database".to_owned(),
|
"Db" => "Database".to_owned(),
|
||||||
"user" => "User".to_owned(),
|
"User" => "User".to_owned(),
|
||||||
"select_priv" => "Select".to_owned(),
|
"select_priv" => "Select".to_owned(),
|
||||||
"insert_priv" => "Insert".to_owned(),
|
"insert_priv" => "Insert".to_owned(),
|
||||||
"update_priv" => "Update".to_owned(),
|
"update_priv" => "Update".to_owned(),
|
||||||
|
@ -128,8 +128,8 @@ pub fn format_privileges_line_for_editor(
|
||||||
DATABASE_PRIVILEGE_FIELDS
|
DATABASE_PRIVILEGE_FIELDS
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|field| match field {
|
.map(|field| match field {
|
||||||
"db" => format!("{:width$}", privs.db, width = database_name_len),
|
"Db" => format!("{:width$}", privs.db, width = database_name_len),
|
||||||
"user" => format!("{:width$}", privs.user, width = username_len),
|
"User" => format!("{:width$}", privs.user, width = username_len),
|
||||||
privilege => format!(
|
privilege => format!(
|
||||||
"{:width$}",
|
"{:width$}",
|
||||||
yn(privs.get_privilege_by_name(privilege)),
|
yn(privs.get_privilege_by_name(privilege)),
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::core::common::UnixUser;
|
use crate::core::common::UnixUser;
|
||||||
|
use sqlx::prelude::*;
|
||||||
|
|
||||||
/// This function creates a regex that matches items (users, databases)
|
/// This function creates a regex that matches items (users, databases)
|
||||||
/// that belong to the user or any of the user's groups.
|
/// that belong to the user or any of the user's groups.
|
||||||
|
@ -9,3 +10,17 @@ pub fn create_user_group_matching_regex(user: &UnixUser) -> String {
|
||||||
format!("({}|{})(_.+)?", user.username, user.groups.join("|"))
|
format!("({}|{})(_.+)?", user.username, user.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: https://github.com/launchbadge/sqlx/issues/3387
|
||||||
|
#[inline]
|
||||||
|
pub fn try_get_with_binary_fallback(
|
||||||
|
row: &sqlx::mysql::MySqlRow,
|
||||||
|
column: &str,
|
||||||
|
) -> Result<String, sqlx::Error> {
|
||||||
|
row.try_get(column).or_else(|_| {
|
||||||
|
row.try_get::<Vec<u8>, _>(column)
|
||||||
|
.map(|v| String::from_utf8_lossy(&v).to_string())
|
||||||
|
})
|
||||||
|
}
|
|
@ -32,7 +32,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
server::{
|
server::{
|
||||||
common::create_user_group_matching_regex,
|
common::{create_user_group_matching_regex, try_get_with_binary_fallback},
|
||||||
input_sanitization::{quote_identifier, validate_name, validate_ownership_by_unix_user},
|
input_sanitization::{quote_identifier, validate_name, validate_ownership_by_unix_user},
|
||||||
sql::database_operations::unsafe_database_exists,
|
sql::database_operations::unsafe_database_exists,
|
||||||
},
|
},
|
||||||
|
@ -42,8 +42,8 @@ use crate::{
|
||||||
/// from the `db` table in the database. If you need to add or remove privilege
|
/// from the `db` table in the database. If you need to add or remove privilege
|
||||||
/// fields, this is a good place to start.
|
/// fields, this is a good place to start.
|
||||||
pub const DATABASE_PRIVILEGE_FIELDS: [&str; 13] = [
|
pub const DATABASE_PRIVILEGE_FIELDS: [&str; 13] = [
|
||||||
"db",
|
"Db",
|
||||||
"user",
|
"User",
|
||||||
"select_priv",
|
"select_priv",
|
||||||
"insert_priv",
|
"insert_priv",
|
||||||
"update_priv",
|
"update_priv",
|
||||||
|
@ -97,6 +97,8 @@ impl DatabasePrivilegeRow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: get by name instead of row tuple position
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_mysql_row_priv_field(row: &MySqlRow, position: usize) -> Result<bool, sqlx::Error> {
|
fn get_mysql_row_priv_field(row: &MySqlRow, position: usize) -> Result<bool, sqlx::Error> {
|
||||||
let field = DATABASE_PRIVILEGE_FIELDS[position];
|
let field = DATABASE_PRIVILEGE_FIELDS[position];
|
||||||
|
@ -113,8 +115,8 @@ fn get_mysql_row_priv_field(row: &MySqlRow, position: usize) -> Result<bool, sql
|
||||||
impl FromRow<'_, MySqlRow> for DatabasePrivilegeRow {
|
impl FromRow<'_, MySqlRow> for DatabasePrivilegeRow {
|
||||||
fn from_row(row: &MySqlRow) -> Result<Self, sqlx::Error> {
|
fn from_row(row: &MySqlRow) -> Result<Self, sqlx::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
db: row.try_get("db")?,
|
db: try_get_with_binary_fallback(row, "Db")?,
|
||||||
user: row.try_get("user")?,
|
user: try_get_with_binary_fallback(row, "User")?,
|
||||||
select_priv: get_mysql_row_priv_field(row, 2)?,
|
select_priv: get_mysql_row_priv_field(row, 2)?,
|
||||||
insert_priv: get_mysql_row_priv_field(row, 3)?,
|
insert_priv: get_mysql_row_priv_field(row, 3)?,
|
||||||
update_priv: get_mysql_row_priv_field(row, 4)?,
|
update_priv: get_mysql_row_priv_field(row, 4)?,
|
||||||
|
@ -137,7 +139,7 @@ async fn unsafe_get_database_privileges(
|
||||||
connection: &mut MySqlConnection,
|
connection: &mut MySqlConnection,
|
||||||
) -> Result<Vec<DatabasePrivilegeRow>, sqlx::Error> {
|
) -> Result<Vec<DatabasePrivilegeRow>, sqlx::Error> {
|
||||||
let result = sqlx::query_as::<_, DatabasePrivilegeRow>(&format!(
|
let result = sqlx::query_as::<_, DatabasePrivilegeRow>(&format!(
|
||||||
"SELECT {} FROM `db` WHERE `db` = ?",
|
"SELECT {} FROM `db` WHERE `Db` = ?",
|
||||||
DATABASE_PRIVILEGE_FIELDS
|
DATABASE_PRIVILEGE_FIELDS
|
||||||
.iter()
|
.iter()
|
||||||
.map(|field| quote_identifier(field))
|
.map(|field| quote_identifier(field))
|
||||||
|
@ -166,7 +168,7 @@ pub async fn unsafe_get_database_privileges_for_db_user_pair(
|
||||||
connection: &mut MySqlConnection,
|
connection: &mut MySqlConnection,
|
||||||
) -> Result<Option<DatabasePrivilegeRow>, sqlx::Error> {
|
) -> Result<Option<DatabasePrivilegeRow>, sqlx::Error> {
|
||||||
let result = sqlx::query_as::<_, DatabasePrivilegeRow>(&format!(
|
let result = sqlx::query_as::<_, DatabasePrivilegeRow>(&format!(
|
||||||
"SELECT {} FROM `db` WHERE `db` = ? AND `user` = ?",
|
"SELECT {} FROM `db` WHERE `Db` = ? AND `User` = ?",
|
||||||
DATABASE_PRIVILEGE_FIELDS
|
DATABASE_PRIVILEGE_FIELDS
|
||||||
.iter()
|
.iter()
|
||||||
.map(|field| quote_identifier(field))
|
.map(|field| quote_identifier(field))
|
||||||
|
@ -316,7 +318,7 @@ async fn unsafe_apply_privilege_diff(
|
||||||
.join(",");
|
.join(",");
|
||||||
|
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
format!("UPDATE `db` SET {} WHERE `db` = ? AND `user` = ?", changes).as_str(),
|
format!("UPDATE `db` SET {} WHERE `Db` = ? AND `User` = ?", changes).as_str(),
|
||||||
)
|
)
|
||||||
.bind(p.db.to_string())
|
.bind(p.db.to_string())
|
||||||
.bind(p.user.to_string())
|
.bind(p.user.to_string())
|
||||||
|
@ -325,7 +327,7 @@ async fn unsafe_apply_privilege_diff(
|
||||||
.map(|_| ())
|
.map(|_| ())
|
||||||
}
|
}
|
||||||
DatabasePrivilegesDiff::Deleted(p) => {
|
DatabasePrivilegesDiff::Deleted(p) => {
|
||||||
sqlx::query("DELETE FROM `db` WHERE `db` = ? AND `user` = ?")
|
sqlx::query("DELETE FROM `db` WHERE `Db` = ? AND `User` = ?")
|
||||||
.bind(p.db.to_string())
|
.bind(p.db.to_string())
|
||||||
.bind(p.user.to_string())
|
.bind(p.user.to_string())
|
||||||
.execute(connection)
|
.execute(connection)
|
||||||
|
|
|
@ -7,6 +7,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use sqlx::prelude::*;
|
use sqlx::prelude::*;
|
||||||
use sqlx::MySqlConnection;
|
use sqlx::MySqlConnection;
|
||||||
|
|
||||||
|
use crate::server::common::try_get_with_binary_fallback;
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{
|
core::{
|
||||||
common::UnixUser,
|
common::UnixUser,
|
||||||
|
@ -350,20 +351,6 @@ pub struct DatabaseUser {
|
||||||
pub databases: Vec<String>,
|
pub databases: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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: https://github.com/launchbadge/sqlx/issues/3387
|
|
||||||
#[inline]
|
|
||||||
fn try_get_with_binary_fallback(
|
|
||||||
row: &sqlx::mysql::MySqlRow,
|
|
||||||
column: &str,
|
|
||||||
) -> Result<String, sqlx::Error> {
|
|
||||||
row.try_get(column).or_else(|_| {
|
|
||||||
row.try_get::<Vec<u8>, _>(column)
|
|
||||||
.map(|v| String::from_utf8_lossy(&v).to_string())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromRow<'_, sqlx::mysql::MySqlRow> for DatabaseUser {
|
impl FromRow<'_, sqlx::mysql::MySqlRow> for DatabaseUser {
|
||||||
fn from_row(row: &sqlx::mysql::MySqlRow) -> Result<Self, sqlx::Error> {
|
fn from_row(row: &sqlx::mysql::MySqlRow) -> Result<Self, sqlx::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
|
Loading…
Reference in New Issue