Add dumping the user db

This commit is contained in:
Nadja Reitzenstein 2022-07-24 16:39:33 +02:00
parent 218a316571
commit aeaae4cd7b
6 changed files with 81 additions and 22 deletions

View File

@ -56,7 +56,8 @@ impl manage::Server for Users {
.get_all()
.map_err(|e| capnp::Error::failed(format!("UserDB error: {:?}", e))));
let mut builder = result.get().init_user_list(users.len() as u32);
for (i, (_, user)) in users.into_iter().enumerate() {
for (i, (id, userdata)) in users.into_iter().enumerate() {
let user = db::User { id, userdata };
User::fill(&self.session, user, builder.reborrow().get(i as u32));
}

View File

@ -65,7 +65,6 @@ use lightproc::recoverable_handle::RecoverableHandle;
use signal_hook::consts::signal::*;
use tracing::Span;
pub struct Diflouroborane {
config: Config,
executor: Executor<'static>,
@ -84,8 +83,7 @@ impl error::Description for SignalHandlerErr {
}
impl Diflouroborane {
pub fn setup() {
}
pub fn setup() {}
pub fn new(config: Config) -> miette::Result<Self> {
let mut server = logging::init(&config.logging);
@ -208,4 +206,4 @@ impl ShutdownHandler {
handle.cancel()
}
}
}
}

View File

@ -1,9 +1,9 @@
use std::path::Path;
use tracing_subscriber::{EnvFilter, reload};
use serde::{Deserialize, Serialize};
use std::path::Path;
use tracing_subscriber::fmt::format::Format;
use tracing_subscriber::prelude::*;
use tracing_subscriber::reload::Handle;
use tracing_subscriber::{reload, EnvFilter};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogConfig {
@ -35,7 +35,7 @@ pub enum LogOutput<'a> {
pub struct LogConfig2<'a, F> {
output: LogOutput<'a>,
filter_str: Option<&'a str>,
format: Format<F>
format: Format<F>,
}
pub fn init(config: &LogConfig) -> console::Server {
@ -56,20 +56,15 @@ pub fn init(config: &LogConfig) -> console::Server {
match format.as_ref() {
"pretty" => {
let fmt_layer = fmt_layer
.pretty()
.with_filter(filter);
let fmt_layer = fmt_layer.pretty().with_filter(filter);
subscriber.with(fmt_layer).init();
}
"compact" => {
let fmt_layer = fmt_layer
.compact()
.with_filter(filter);
let fmt_layer = fmt_layer.compact().with_filter(filter);
subscriber.with(fmt_layer).init();
}
_ => {
let fmt_layer = fmt_layer
.with_filter(filter);
let fmt_layer = fmt_layer.with_filter(filter);
subscriber.with(fmt_layer).init();
}
}

View File

@ -187,15 +187,15 @@ impl UserDB {
Ok(())
}
pub fn get_all(&self) -> Result<Vec<(String, User)>, db::Error> {
pub fn get_all(&self) -> Result<HashMap<String, UserData>, db::Error> {
let txn = self.env.begin_ro_txn()?;
let iter = self.db.get_all(&txn)?;
let mut out = Vec::new();
let mut out = HashMap::new();
for (uid, user) in iter {
let uid = unsafe { std::str::from_utf8_unchecked(uid).to_string() };
let user: User =
Deserialize::<User, _>::deserialize(user.as_ref(), &mut Infallible).unwrap();
out.push((uid, user));
out.insert(uid, user.userdata);
}
Ok(out)

View File

@ -1,8 +1,11 @@
use std::fs;
use lmdb::{Environment, Transaction};
use once_cell::sync::OnceCell;
use rkyv::{Archive, Deserialize, Infallible, Serialize};
use std::collections::HashMap;
use std::fmt::{Display, Formatter, Write};
use std::fmt::{Display, Formatter};
use std::io::Write;
use clap::ArgMatches;
use miette::{Context, Diagnostic, IntoDiagnostic, SourceOffset, SourceSpan};
@ -166,4 +169,41 @@ impl Users {
txn.commit().map_err(crate::db::Error::from)?;
Ok(())
}
pub fn dump_file(&self, path_str: &str, force: bool) -> miette::Result<usize> {
let path = Path::new(path_str);
let exists = path.exists();
if exists {
if !force {
#[derive(Debug, Error, Diagnostic)]
#[error("given file already exists, refusing to clobber")]
#[diagnostic(code(dump::clobber))]
struct DumpFileExists {
#[source_code]
src: String,
#[label("file provided")]
dir_path: SourceSpan,
#[help]
help: &'static str,
}
Err(DumpFileExists {
src: format!("--load {}", path_str),
dir_path: (7, path_str.as_bytes().len()).into(),
help: "to force overwriting the file add `--force` as argument",
})?;
} else {
tracing::info!("output file already exists, overwriting due to `--force`");
}
}
let mut file = fs::File::create(path).into_diagnostic()?;
let users = self.userdb.get_all()?;
let encoded = toml::ser::to_vec(&users).into_diagnostic()?;
file.write_all(&encoded[..]).into_diagnostic()?;
Ok(0)
}
}

View File

@ -1,4 +1,4 @@
use clap::{Arg, Command};
use clap::{Arg, Command, ValueHint};
use diflouroborane::{config, Diflouroborane};
use std::str::FromStr;
@ -61,6 +61,20 @@ fn main() -> miette::Result<()> {
.help("Dump all internal databases")
.long("dump")
.conflicts_with("load"))
.arg(
Arg::new("dump-users")
.help("Dump the users db to the given file as TOML")
.long("dump-users")
.takes_value(true)
.value_name("FILE")
.value_hint(ValueHint::AnyPath)
.default_missing_value("users.toml")
.conflicts_with("load"))
.arg(
Arg::new("force")
.help("force ops that may clobber")
.long("force")
)
.arg(
Arg::new("load")
.help("Load values into the internal databases")
@ -124,7 +138,18 @@ fn main() -> miette::Result<()> {
let mut config = config::read(&PathBuf::from_str(configpath).unwrap()).unwrap();
if matches.is_present("dump") {
unimplemented!()
return Err(miette::miette!("DB Dumping is currently not implemented, except for the users db, using `--dump-users`"));
} else if matches.is_present("dump-users") {
let bffh = Diflouroborane::new(config)?;
let number = bffh.users.dump_file(
matches.value_of("dump-users").unwrap(),
matches.is_present("force"),
)?;
tracing::info!("successfully dumped {} users", number);
return Ok(());
} else if matches.is_present("load") {
let bffh = Diflouroborane::new(config)?;