Compare commits
1 Commits
publish-de
...
dpkg-packa
Author | SHA1 | Date | |
---|---|---|---|
3c84dd5be1
|
@@ -1,32 +0,0 @@
|
|||||||
name: "publish-deb"
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
version:
|
|
||||||
description: "Version to publish"
|
|
||||||
required: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Install rust toolchain
|
|
||||||
uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
toolchain: stable
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Install cargo-deb
|
|
||||||
run: cargo install cargo-deb
|
|
||||||
|
|
||||||
- name: Build deb package
|
|
||||||
run: ./create-deb.sh
|
|
||||||
|
|
||||||
- name: Publish deb package
|
|
||||||
run: |
|
|
||||||
curl \
|
|
||||||
--user your_username:your_password_or_token \
|
|
||||||
--upload-file target/debian/*.deb \
|
|
||||||
https://git.pvv.ntnu.no/api/packages/testuser/debian/pool/bionic/main/upload
|
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -6,3 +6,6 @@ config.toml
|
|||||||
/.direnv/
|
/.direnv/
|
||||||
result
|
result
|
||||||
result-*
|
result-*
|
||||||
|
|
||||||
|
# Packaging
|
||||||
|
/assets/completions/
|
653
Cargo.lock
generated
653
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
60
Cargo.toml
60
Cargo.toml
@@ -2,26 +2,36 @@
|
|||||||
name = "mysqladm-rs"
|
name = "mysqladm-rs"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
license = "BSD3"
|
||||||
|
authors = [
|
||||||
|
"oysteikt@pvv.ntnu.no",
|
||||||
|
"felixalb@pvv.ntnu.no",
|
||||||
|
]
|
||||||
|
repository = "https://git.pvv.ntnu.no/Projects/mysqladm-rs"
|
||||||
|
description = "A command-line utility for MySQL administration for non-admin users"
|
||||||
|
categories = ["command-line-interface", "command-line-utilities"]
|
||||||
|
keywords = ["mysql", "cli", "administration"]
|
||||||
|
readme = "README.md"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.95"
|
anyhow = "1.0.95"
|
||||||
async-bincode = "0.8.0"
|
async-bincode = "0.7.3"
|
||||||
bincode = "2.0.1"
|
bincode = "1.3.3"
|
||||||
clap = { version = "4.5.26", features = ["derive"] }
|
clap = { version = "4.5.26", features = ["derive"] }
|
||||||
clap-verbosity-flag = "3.0.2"
|
clap-verbosity-flag = "2.2.3"
|
||||||
clap_complete = "4.5.42"
|
clap_complete = "4.5.42"
|
||||||
derive_more = { version = "2.0.1", features = ["display", "error"] }
|
derive_more = { version = "1.0.0", features = ["display", "error"] }
|
||||||
dialoguer = "0.11.0"
|
dialoguer = "0.11.0"
|
||||||
env_logger = "0.11.6"
|
env_logger = "0.11.6"
|
||||||
futures = "0.3.31"
|
futures = "0.3.31"
|
||||||
futures-util = "0.3.31"
|
futures-util = "0.3.31"
|
||||||
indoc = "2.0.5"
|
indoc = "2.0.5"
|
||||||
itertools = "0.14.0"
|
itertools = "0.13.0"
|
||||||
log = "0.4.25"
|
log = "0.4.25"
|
||||||
nix = { version = "0.30.1", features = ["fs", "process", "socket", "user"] }
|
nix = { version = "0.29.0", features = ["fs", "process", "socket", "user"] }
|
||||||
prettytable = "0.10.0"
|
prettytable = "0.10.0"
|
||||||
rand = "0.9.1"
|
rand = "0.8.5"
|
||||||
ratatui = { version = "0.29.0", optional = true }
|
ratatui = { version = "0.28.1", optional = true }
|
||||||
sd-notify = "0.4.5"
|
sd-notify = "0.4.5"
|
||||||
serde = "1.0.217"
|
serde = "1.0.217"
|
||||||
serde_json = { version = "1.0.135", features = ["preserve_order"] }
|
serde_json = { version = "1.0.135", features = ["preserve_order"] }
|
||||||
@@ -54,3 +64,37 @@ anyhow = "1.0.95"
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
|
|
||||||
|
# TODO: package shell completions
|
||||||
|
[package.metadata.deb]
|
||||||
|
maintainer = "Programvareverkstedet <projects@pvv.ntnu.no>"
|
||||||
|
section = "admin"
|
||||||
|
assets = [
|
||||||
|
[
|
||||||
|
"target/release/mysqladm",
|
||||||
|
"usr/bin/",
|
||||||
|
"755",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"example-config.toml",
|
||||||
|
"etc/mysqladm/config.toml",
|
||||||
|
"644",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"assets/completions/_*",
|
||||||
|
"usr/share/zsh/site-functions/completions/",
|
||||||
|
"644",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"assets/completions/*.bash",
|
||||||
|
"usr/share/bash-completion/completions/",
|
||||||
|
"644",
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"assets/completions/*.fish",
|
||||||
|
"usr/share/fish/vendor_completions.d/",
|
||||||
|
"644",
|
||||||
|
],
|
||||||
|
]
|
||||||
|
conf-files = ["etc/mysqladm/config.toml"]
|
||||||
|
depends = []
|
||||||
|
21
README.md
21
README.md
@@ -2,26 +2,7 @@
|
|||||||
|
|
||||||
# mysqladm-rs
|
# mysqladm-rs
|
||||||
|
|
||||||
Healing mysql spasms since 2024
|
Work in progress rewrite of https://git.pvv.ntnu.no/Projects/mysql-admutils
|
||||||
|
|
||||||
## What is this?
|
|
||||||
|
|
||||||
This is a CLI tool that let's normal users perform administrative operations on a MySQL DBMS, with some restrictions.
|
|
||||||
The default restriction is to only let the user perform these actions on databases and database users that are prefixed with their username,
|
|
||||||
or with the name of any unix group that the user is a part of. i.e. `<user>_mydb`, `<user>_mydbuser`, or `<group>_myotherdb`.
|
|
||||||
|
|
||||||
The administrative actions available to the user includes:
|
|
||||||
|
|
||||||
- creating/listing/modifying/deleting databases and database users
|
|
||||||
- modifying database user privileges
|
|
||||||
- changing the passwords of the database users
|
|
||||||
- locking and unlocking database user accounts
|
|
||||||
- ... more to come
|
|
||||||
|
|
||||||
The software is split into a client and a server. The server has administrative access to the mysql server,
|
|
||||||
and is responsible for checking client authorization for the different types of actions the client might request.
|
|
||||||
|
|
||||||
This is designed for (and is only really useful for) multi-user servers, like tilde servers, university unix servers, etc.
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
19
create-deb.sh
Executable file
19
create-deb.sh
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
cargo build --release
|
||||||
|
|
||||||
|
mkdir -p assets/completions
|
||||||
|
|
||||||
|
./target/release/mysqladm generate-completions --shell bash > assets/completions/mysqladm.bash
|
||||||
|
./target/release/mysqladm generate-completions --shell zsh > assets/completions/_mysqladm
|
||||||
|
./target/release/mysqladm generate-completions --shell fish > assets/completions/mysqladm.fish
|
||||||
|
|
||||||
|
./target/release/mysqladm generate-completions --shell bash --command mysql-dbadm > assets/completions/mysql-dbadm.bash
|
||||||
|
./target/release/mysqladm generate-completions --shell zsh --command mysql-dbadm > assets/completions/_mysql-dbadm
|
||||||
|
./target/release/mysqladm generate-completions --shell fish --command mysql-dbadm > assets/completions/mysql-dbadm.fish
|
||||||
|
|
||||||
|
./target/release/mysqladm generate-completions --shell bash --command mysql-useradm > assets/completions/mysql-useradm.bash
|
||||||
|
./target/release/mysqladm generate-completions --shell zsh --command mysql-useradm > assets/completions/_mysql-useradm
|
||||||
|
./target/release/mysqladm generate-completions --shell fish --command mysql-useradm > assets/completions/mysql-useradm.fish
|
||||||
|
|
||||||
|
cargo deb
|
@@ -19,4 +19,4 @@ port = 3306
|
|||||||
username = "root"
|
username = "root"
|
||||||
password = "secret"
|
password = "secret"
|
||||||
|
|
||||||
timeout = 2 # seconds
|
timeout = 2 # seconds
|
||||||
|
12
flake.lock
generated
12
flake.lock
generated
@@ -2,11 +2,11 @@
|
|||||||
"nodes": {
|
"nodes": {
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1746461020,
|
"lastModified": 1737062831,
|
||||||
"narHash": "sha256-7+pG1I9jvxNlmln4YgnlW4o+w0TZX24k688mibiFDUE=",
|
"narHash": "sha256-Tbk1MZbtV2s5aG+iM99U8FqwxU/YNArMcWAv6clcsBc=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "3730d8a308f94996a9ba7c7138ede69c1b9ac4ae",
|
"rev": "5df43628fdf08d642be8ba5b3625a6c70731c19c",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -29,11 +29,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1746585402,
|
"lastModified": 1737166965,
|
||||||
"narHash": "sha256-Pf+ufu6bYNA1+KQKHnGMNEfTwpD9ZIcAeLoE2yPWIP0=",
|
"narHash": "sha256-vlDROBAgq+7PEVM0vaS2zboY6DXs3oKK0qW/1dVuFs4=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "72dd969389583664f87aa348b3458f2813693617",
|
"rev": "fc839c9d5d1ebc789b4657c43c4d54838c7c01de",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@@ -48,6 +48,7 @@
|
|||||||
mysql-client
|
mysql-client
|
||||||
cargo-nextest
|
cargo-nextest
|
||||||
cargo-deny
|
cargo-deny
|
||||||
|
cargo-deb
|
||||||
];
|
];
|
||||||
|
|
||||||
RUST_SRC_PATH = "${toolchain}/lib/rustlib/src/rust/library";
|
RUST_SRC_PATH = "${toolchain}/lib/rustlib/src/rust/library";
|
||||||
|
@@ -1 +0,0 @@
|
|||||||
style_edition = "2024"
|
|
@@ -2,7 +2,7 @@ use anyhow::Context;
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use dialoguer::{Confirm, Editor};
|
use dialoguer::{Confirm, Editor};
|
||||||
use futures_util::{SinkExt, StreamExt};
|
use futures_util::{SinkExt, StreamExt};
|
||||||
use nix::unistd::{User, getuid};
|
use nix::unistd::{getuid, User};
|
||||||
use prettytable::{Cell, Row, Table};
|
use prettytable::{Cell, Row, Table};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -15,13 +15,13 @@ use crate::{
|
|||||||
parse_privilege_table_cli_arg,
|
parse_privilege_table_cli_arg,
|
||||||
},
|
},
|
||||||
protocol::{
|
protocol::{
|
||||||
ClientToServerMessageStream, MySQLDatabase, Request, Response,
|
|
||||||
print_create_databases_output_status, print_create_databases_output_status_json,
|
print_create_databases_output_status, print_create_databases_output_status_json,
|
||||||
print_drop_databases_output_status, print_drop_databases_output_status_json,
|
print_drop_databases_output_status, print_drop_databases_output_status_json,
|
||||||
print_modify_database_privileges_output_status,
|
print_modify_database_privileges_output_status, ClientToServerMessageStream,
|
||||||
|
MySQLDatabase, Request, Response,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
server::sql::database_privilege_operations::{DATABASE_PRIVILEGE_FIELDS, DatabasePrivilegeRow},
|
server::sql::database_privilege_operations::{DatabasePrivilegeRow, DATABASE_PRIVILEGE_FIELDS},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Parser, Debug, Clone)]
|
#[derive(Parser, Debug, Clone)]
|
||||||
|
@@ -19,8 +19,8 @@ use crate::{
|
|||||||
core::{
|
core::{
|
||||||
bootstrap::bootstrap_server_connection_and_drop_privileges,
|
bootstrap::bootstrap_server_connection_and_drop_privileges,
|
||||||
protocol::{
|
protocol::{
|
||||||
ClientToServerMessageStream, GetDatabasesPrivilegeDataError, MySQLDatabase, Request,
|
create_client_to_server_message_stream, ClientToServerMessageStream,
|
||||||
Response, create_client_to_server_message_stream,
|
GetDatabasesPrivilegeDataError, MySQLDatabase, Request, Response,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
server::sql::database_privilege_operations::DatabasePrivilegeRow,
|
server::sql::database_privilege_operations::DatabasePrivilegeRow,
|
||||||
@@ -307,7 +307,11 @@ async fn show_databases(
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn yn(value: bool) -> &'static str {
|
fn yn(value: bool) -> &'static str {
|
||||||
if value { "Y" } else { "N" }
|
if value {
|
||||||
|
"Y"
|
||||||
|
} else {
|
||||||
|
"N"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_db_privs(name: &str, rows: Vec<DatabasePrivilegeRow>) -> anyhow::Result<()> {
|
fn print_db_privs(name: &str, rows: Vec<DatabasePrivilegeRow>) -> anyhow::Result<()> {
|
||||||
|
@@ -19,8 +19,8 @@ use crate::{
|
|||||||
core::{
|
core::{
|
||||||
bootstrap::bootstrap_server_connection_and_drop_privileges,
|
bootstrap::bootstrap_server_connection_and_drop_privileges,
|
||||||
protocol::{
|
protocol::{
|
||||||
ClientToServerMessageStream, MySQLUser, Request, Response,
|
create_client_to_server_message_stream, ClientToServerMessageStream, MySQLUser,
|
||||||
create_client_to_server_message_stream,
|
Request, Response,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
server::sql::user_operations::DatabaseUser,
|
server::sql::user_operations::DatabaseUser,
|
||||||
|
@@ -4,12 +4,12 @@ use dialoguer::{Confirm, Password};
|
|||||||
use futures_util::{SinkExt, StreamExt};
|
use futures_util::{SinkExt, StreamExt};
|
||||||
|
|
||||||
use crate::core::protocol::{
|
use crate::core::protocol::{
|
||||||
ClientToServerMessageStream, ListUsersError, MySQLUser, Request, Response,
|
|
||||||
print_create_users_output_status, print_create_users_output_status_json,
|
print_create_users_output_status, print_create_users_output_status_json,
|
||||||
print_drop_users_output_status, print_drop_users_output_status_json,
|
print_drop_users_output_status, print_drop_users_output_status_json,
|
||||||
print_lock_users_output_status, print_lock_users_output_status_json,
|
print_lock_users_output_status, print_lock_users_output_status_json,
|
||||||
print_set_password_output_status, print_unlock_users_output_status,
|
print_set_password_output_status, print_unlock_users_output_status,
|
||||||
print_unlock_users_output_status_json,
|
print_unlock_users_output_status_json, ClientToServerMessageStream, ListUsersError, MySQLUser,
|
||||||
|
Request, Response,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::common::erroneous_server_response;
|
use super::common::erroneous_server_response;
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
use std::{fs, path::PathBuf};
|
use std::{fs, path::PathBuf};
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use nix::libc::{EXIT_SUCCESS, exit};
|
use nix::libc::{exit, EXIT_SUCCESS};
|
||||||
use std::os::unix::net::UnixStream as StdUnixStream;
|
use std::os::unix::net::UnixStream as StdUnixStream;
|
||||||
use tokio::net::UnixStream as TokioUnixStream;
|
use tokio::net::UnixStream as TokioUnixStream;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::common::{DEFAULT_CONFIG_PATH, DEFAULT_SOCKET_PATH, UnixUser},
|
core::common::{UnixUser, DEFAULT_CONFIG_PATH, DEFAULT_SOCKET_PATH},
|
||||||
server::{config::read_config_from_path, server_loop::handle_requests_for_single_session},
|
server::{config::read_config_from_path, server_loop::handle_requests_for_single_session},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -66,7 +66,11 @@ impl UnixUser {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) fn yn(b: bool) -> &'static str {
|
pub(crate) fn yn(b: bool) -> &'static str {
|
||||||
if b { "Y" } else { "N" }
|
if b {
|
||||||
|
"Y"
|
||||||
|
} else {
|
||||||
|
"N"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
use anyhow::{Context, anyhow};
|
use anyhow::{anyhow, Context};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use prettytable::Table;
|
use prettytable::Table;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -12,7 +12,7 @@ use super::{
|
|||||||
protocol::{MySQLDatabase, MySQLUser},
|
protocol::{MySQLDatabase, MySQLUser},
|
||||||
};
|
};
|
||||||
use crate::server::sql::database_privilege_operations::{
|
use crate::server::sql::database_privilege_operations::{
|
||||||
DATABASE_PRIVILEGE_FIELDS, DatabasePrivilegeRow,
|
DatabasePrivilegeRow, DATABASE_PRIVILEGE_FIELDS,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn db_priv_field_human_readable_name(name: &str) -> String {
|
pub fn db_priv_field_human_readable_name(name: &str) -> String {
|
||||||
@@ -288,10 +288,10 @@ fn parse_privilege_row_from_editor(row: &str) -> PrivilegeRowParseResult {
|
|||||||
|
|
||||||
match parts.len() {
|
match parts.len() {
|
||||||
n if (n < DATABASE_PRIVILEGE_FIELDS.len()) => {
|
n if (n < DATABASE_PRIVILEGE_FIELDS.len()) => {
|
||||||
return PrivilegeRowParseResult::TooFewFields(n);
|
return PrivilegeRowParseResult::TooFewFields(n)
|
||||||
}
|
}
|
||||||
n if (n > DATABASE_PRIVILEGE_FIELDS.len()) => {
|
n if (n > DATABASE_PRIVILEGE_FIELDS.len()) => {
|
||||||
return PrivilegeRowParseResult::TooManyFields(n);
|
return PrivilegeRowParseResult::TooManyFields(n)
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,7 @@ use std::{
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tokio::net::UnixStream;
|
use tokio::net::UnixStream;
|
||||||
use tokio_serde::{Framed as SerdeFramed, formats::Bincode};
|
use tokio_serde::{formats::Bincode, Framed as SerdeFramed};
|
||||||
use tokio_util::codec::{Framed, LengthDelimitedCodec};
|
use tokio_util::codec::{Framed, LengthDelimitedCodec};
|
||||||
|
|
||||||
use crate::core::{database_privileges::DatabasePrivilegesDiff, protocol::*};
|
use crate::core::{database_privileges::DatabasePrivilegesDiff, protocol::*};
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
extern crate prettytable;
|
extern crate prettytable;
|
||||||
|
|
||||||
use clap::{CommandFactory, Parser, ValueEnum};
|
use clap::{CommandFactory, Parser, ValueEnum};
|
||||||
use clap_complete::{Shell, generate};
|
use clap_complete::{generate, Shell};
|
||||||
use clap_verbosity_flag::Verbosity;
|
use clap_verbosity_flag::Verbosity;
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
@@ -15,7 +15,7 @@ use futures::StreamExt;
|
|||||||
use crate::{
|
use crate::{
|
||||||
core::{
|
core::{
|
||||||
bootstrap::bootstrap_server_connection_and_drop_privileges,
|
bootstrap::bootstrap_server_connection_and_drop_privileges,
|
||||||
protocol::{Response, create_client_to_server_message_stream},
|
protocol::{create_client_to_server_message_stream, Response},
|
||||||
},
|
},
|
||||||
server::command::ServerArgs,
|
server::command::ServerArgs,
|
||||||
};
|
};
|
||||||
|
@@ -12,7 +12,7 @@ use std::os::unix::net::UnixStream as StdUnixStream;
|
|||||||
use tokio::net::UnixStream as TokioUnixStream;
|
use tokio::net::UnixStream as TokioUnixStream;
|
||||||
|
|
||||||
use crate::core::common::UnixUser;
|
use crate::core::common::UnixUser;
|
||||||
use crate::core::protocol::{Response, create_server_to_client_message_stream};
|
use crate::core::protocol::{create_server_to_client_message_stream, Response};
|
||||||
use crate::server::config::read_config_from_path_with_arg_overrides;
|
use crate::server::config::read_config_from_path_with_arg_overrides;
|
||||||
use crate::server::server_loop::listen_for_incoming_connections;
|
use crate::server::server_loop::listen_for_incoming_connections;
|
||||||
use crate::server::{
|
use crate::server::{
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
use std::{fs, path::PathBuf, time::Duration};
|
use std::{fs, path::PathBuf, time::Duration};
|
||||||
|
|
||||||
use anyhow::{Context, anyhow};
|
use anyhow::{anyhow, Context};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::{ConnectOptions, MySqlConnection, mysql::MySqlConnectOptions};
|
use sqlx::{mysql::MySqlConnectOptions, ConnectOptions, MySqlConnection};
|
||||||
|
|
||||||
use crate::core::common::DEFAULT_CONFIG_PATH;
|
use crate::core::common::DEFAULT_CONFIG_PATH;
|
||||||
|
|
||||||
|
@@ -4,20 +4,20 @@ use futures_util::{SinkExt, StreamExt};
|
|||||||
use indoc::concatdoc;
|
use indoc::concatdoc;
|
||||||
use tokio::net::{UnixListener, UnixStream};
|
use tokio::net::{UnixListener, UnixStream};
|
||||||
|
|
||||||
use sqlx::MySqlConnection;
|
|
||||||
use sqlx::prelude::*;
|
use sqlx::prelude::*;
|
||||||
|
use sqlx::MySqlConnection;
|
||||||
|
|
||||||
use crate::core::protocol::SetPasswordError;
|
use crate::core::protocol::SetPasswordError;
|
||||||
use crate::server::sql::database_operations::list_databases;
|
use crate::server::sql::database_operations::list_databases;
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{
|
core::{
|
||||||
common::{DEFAULT_SOCKET_PATH, UnixUser},
|
common::{UnixUser, DEFAULT_SOCKET_PATH},
|
||||||
protocol::request_response::{
|
protocol::request_response::{
|
||||||
Request, Response, ServerToClientMessageStream, create_server_to_client_message_stream,
|
create_server_to_client_message_stream, Request, Response, ServerToClientMessageStream,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
server::{
|
server::{
|
||||||
config::{ServerConfig, create_mysql_connection_from_config},
|
config::{create_mysql_connection_from_config, ServerConfig},
|
||||||
sql::{
|
sql::{
|
||||||
database_operations::{create_databases, drop_databases, list_all_databases_for_user},
|
database_operations::{create_databases, drop_databases, list_all_databases_for_user},
|
||||||
database_privilege_operations::{
|
database_privilege_operations::{
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use sqlx::MySqlConnection;
|
|
||||||
use sqlx::prelude::*;
|
use sqlx::prelude::*;
|
||||||
|
use sqlx::MySqlConnection;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@@ -19,11 +19,11 @@ use std::collections::{BTreeMap, BTreeSet};
|
|||||||
use indoc::indoc;
|
use indoc::indoc;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::{MySqlConnection, mysql::MySqlRow, prelude::*};
|
use sqlx::{mysql::MySqlRow, prelude::*, MySqlConnection};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{
|
core::{
|
||||||
common::{UnixUser, rev_yn, yn},
|
common::{rev_yn, yn, UnixUser},
|
||||||
database_privileges::{DatabasePrivilegeChange, DatabasePrivilegesDiff},
|
database_privileges::{DatabasePrivilegeChange, DatabasePrivilegesDiff},
|
||||||
protocol::{
|
protocol::{
|
||||||
DiffDoesNotApplyError, GetAllDatabasesPrivilegeData, GetAllDatabasesPrivilegeDataError,
|
DiffDoesNotApplyError, GetAllDatabasesPrivilegeData, GetAllDatabasesPrivilegeDataError,
|
||||||
@@ -280,8 +280,9 @@ async fn unsafe_apply_privilege_diff(
|
|||||||
.map(|field| quote_identifier(field))
|
.map(|field| quote_identifier(field))
|
||||||
.join(",");
|
.join(",");
|
||||||
|
|
||||||
let question_marks =
|
let question_marks = std::iter::repeat("?")
|
||||||
std::iter::repeat_n("?", DATABASE_PRIVILEGE_FIELDS.len()).join(",");
|
.take(DATABASE_PRIVILEGE_FIELDS.len())
|
||||||
|
.join(",");
|
||||||
|
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
format!("INSERT INTO `db` ({}) VALUES ({})", tables, question_marks).as_str(),
|
format!("INSERT INTO `db` ({}) VALUES ({})", tables, question_marks).as_str(),
|
||||||
|
@@ -4,8 +4,8 @@ use std::collections::BTreeMap;
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use sqlx::MySqlConnection;
|
|
||||||
use sqlx::prelude::*;
|
use sqlx::prelude::*;
|
||||||
|
use sqlx::MySqlConnection;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
core::{
|
core::{
|
||||||
|
Reference in New Issue
Block a user