Rewrite entire codebase to split into client and server
This commit was merged in pull request #55.
This commit is contained in:
147
src/main.rs
147
src/main.rs
@@ -1,42 +1,69 @@
|
||||
#[macro_use]
|
||||
extern crate prettytable;
|
||||
|
||||
use core::common::CommandStatus;
|
||||
#[cfg(feature = "mysql-admutils-compatibility")]
|
||||
use clap::Parser;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use std::os::unix::net::UnixStream as StdUnixStream;
|
||||
use tokio::net::UnixStream as TokioUnixStream;
|
||||
|
||||
use crate::{
|
||||
core::{
|
||||
bootstrap::{bootstrap_server_connection_and_drop_privileges, drop_privs},
|
||||
protocol::create_client_to_server_message_stream,
|
||||
},
|
||||
server::command::ServerArgs,
|
||||
};
|
||||
|
||||
#[cfg(feature = "mysql-admutils-compatibility")]
|
||||
use crate::cli::mysql_admutils_compatibility::{mysql_dbadm, mysql_useradm};
|
||||
|
||||
use clap::Parser;
|
||||
mod server;
|
||||
|
||||
mod authenticated_unix_socket;
|
||||
mod cli;
|
||||
mod core;
|
||||
|
||||
#[cfg(feature = "tui")]
|
||||
mod tui;
|
||||
|
||||
#[derive(Parser)]
|
||||
#[derive(Parser, Debug)]
|
||||
struct Args {
|
||||
#[command(subcommand)]
|
||||
command: Command,
|
||||
|
||||
#[command(flatten)]
|
||||
config_overrides: core::config::GlobalConfigArgs,
|
||||
/// Path to the socket of the server, if it already exists.
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
value_name = "PATH",
|
||||
global = true,
|
||||
hide_short_help = true
|
||||
)]
|
||||
server_socket_path: Option<PathBuf>,
|
||||
|
||||
/// Config file to use for the server.
|
||||
#[arg(
|
||||
short,
|
||||
long,
|
||||
value_name = "PATH",
|
||||
global = true,
|
||||
hide_short_help = true
|
||||
)]
|
||||
config: Option<PathBuf>,
|
||||
|
||||
#[cfg(feature = "tui")]
|
||||
#[arg(short, long, alias = "tui", global = true)]
|
||||
interactive: bool,
|
||||
}
|
||||
|
||||
/// Database administration tool for non-admin users to manage their own MySQL databases and users.
|
||||
///
|
||||
/// This tool allows you to manage users and databases in MySQL.
|
||||
///
|
||||
/// You are only allowed to manage databases and users that are prefixed with
|
||||
/// either your username, or a group that you are a member of.
|
||||
#[derive(Parser)]
|
||||
// Database administration tool for non-admin users to manage their own MySQL databases and users.
|
||||
//
|
||||
// This tool allows you to manage users and databases in MySQL.
|
||||
//
|
||||
// You are only allowed to manage databases and users that are prefixed with
|
||||
// either your username, or a group that you are a member of.
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
#[command(version, about, disable_help_subcommand = true)]
|
||||
enum Command {
|
||||
#[command(flatten)]
|
||||
@@ -44,10 +71,18 @@ enum Command {
|
||||
|
||||
#[command(flatten)]
|
||||
User(cli::user_command::UserCommand),
|
||||
|
||||
#[command(hide = true)]
|
||||
Server(server::command::ServerArgs),
|
||||
}
|
||||
|
||||
#[tokio::main(flavor = "current_thread")]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
// TODO: tag all functions that are run with elevated privileges with
|
||||
// comments emphasizing the need for caution.
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
// TODO: find out if there are any security risks of running
|
||||
// env_logger and clap with elevated privileges.
|
||||
|
||||
env_logger::init();
|
||||
|
||||
#[cfg(feature = "mysql-admutils-compatibility")]
|
||||
@@ -59,42 +94,60 @@ async fn main() -> anyhow::Result<()> {
|
||||
});
|
||||
|
||||
match argv0.as_deref() {
|
||||
Some("mysql-dbadm") => return mysql_dbadm::main().await,
|
||||
Some("mysql-useradm") => return mysql_useradm::main().await,
|
||||
Some("mysql-dbadm") => return mysql_dbadm::main(),
|
||||
Some("mysql-useradm") => return mysql_useradm::main(),
|
||||
_ => { /* fall through */ }
|
||||
}
|
||||
}
|
||||
|
||||
let args: Args = Args::parse();
|
||||
let config = core::config::get_config(args.config_overrides)?;
|
||||
let connection = core::config::create_mysql_connection_from_config(config.mysql).await?;
|
||||
|
||||
let result = match args.command {
|
||||
Command::Db(command) => cli::database_command::handle_command(command, connection).await,
|
||||
Command::User(user_args) => cli::user_command::handle_command(user_args, connection).await,
|
||||
};
|
||||
|
||||
match result {
|
||||
Ok(CommandStatus::SuccessfullyModified) => {
|
||||
println!("Modifications committed successfully");
|
||||
Ok(())
|
||||
match args.command {
|
||||
Command::Server(ref command) => {
|
||||
drop_privs()?;
|
||||
tokio_start_server(args.server_socket_path, args.config, command.clone())?;
|
||||
return Ok(());
|
||||
}
|
||||
Ok(CommandStatus::PartiallySuccessfullyModified) => {
|
||||
println!("Some modifications committed successfully");
|
||||
Ok(())
|
||||
}
|
||||
Ok(CommandStatus::NoModificationsNeeded) => {
|
||||
println!("No modifications made");
|
||||
Ok(())
|
||||
}
|
||||
Ok(CommandStatus::NoModificationsIntended) => {
|
||||
/* Don't report anything */
|
||||
Ok(())
|
||||
}
|
||||
Ok(CommandStatus::Cancelled) => {
|
||||
println!("Command cancelled successfully");
|
||||
Ok(())
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
_ => { /* fall through */ }
|
||||
}
|
||||
|
||||
let server_connection =
|
||||
bootstrap_server_connection_and_drop_privileges(args.server_socket_path, args.config)?;
|
||||
|
||||
tokio_run_command(args.command, server_connection)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn tokio_start_server(
|
||||
server_socket_path: Option<PathBuf>,
|
||||
config_path: Option<PathBuf>,
|
||||
args: ServerArgs,
|
||||
) -> anyhow::Result<()> {
|
||||
tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
server::command::handle_command(server_socket_path, config_path, args).await
|
||||
})
|
||||
}
|
||||
|
||||
fn tokio_run_command(command: Command, server_connection: StdUnixStream) -> anyhow::Result<()> {
|
||||
tokio::runtime::Builder::new_current_thread()
|
||||
.enable_all()
|
||||
.build()
|
||||
.unwrap()
|
||||
.block_on(async {
|
||||
let tokio_socket = TokioUnixStream::from_std(server_connection)?;
|
||||
let message_stream = create_client_to_server_message_stream(tokio_socket);
|
||||
match command {
|
||||
Command::User(user_args) => {
|
||||
cli::user_command::handle_command(user_args, message_stream).await
|
||||
}
|
||||
Command::Db(db_args) => {
|
||||
cli::database_command::handle_command(db_args, message_stream).await
|
||||
}
|
||||
Command::Server(_) => unreachable!(),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user