mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-14 10:32:19 +00:00
Add some CLI commands to generate a default configuration and password hashes
This commit is contained in:
94
src/commands/mod.rs
Normal file
94
src/commands/mod.rs
Normal file
@@ -0,0 +1,94 @@
|
||||
use argon2::password_hash::SaltString;
|
||||
use clap::{Parser, ValueEnum};
|
||||
use password_hash::PasswordHasher;
|
||||
use pbkdf2::Params;
|
||||
use rand::{rngs::OsRng, RngCore};
|
||||
use rustical_frontend::FrontendConfig;
|
||||
use rustical_store::auth::{static_user_store::UserEntry, StaticUserStoreConfig, User};
|
||||
|
||||
use crate::config::{
|
||||
AuthConfig, Config, DataStoreConfig, HttpConfig, SqliteDataStoreConfig, TracingConfig,
|
||||
};
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct GenConfigArgs {}
|
||||
|
||||
fn generate_frontend_secret() -> [u8; 64] {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let mut secret = [0u8; 64];
|
||||
rng.fill_bytes(&mut secret);
|
||||
secret
|
||||
}
|
||||
|
||||
pub fn cmd_gen_config(_args: GenConfigArgs) -> anyhow::Result<()> {
|
||||
let config = Config {
|
||||
http: HttpConfig::default(),
|
||||
auth: AuthConfig::Static(StaticUserStoreConfig {
|
||||
users: vec![UserEntry {
|
||||
user: User {
|
||||
id: "default".to_owned(),
|
||||
displayname: Some("Default user".to_owned()),
|
||||
password: Some("generate a password hash with rustical pwhash".to_owned()),
|
||||
},
|
||||
app_tokens: vec![],
|
||||
}],
|
||||
}),
|
||||
data_store: DataStoreConfig::Sqlite(SqliteDataStoreConfig {
|
||||
db_url: "".to_owned(),
|
||||
}),
|
||||
tracing: TracingConfig::default(),
|
||||
frontend: FrontendConfig {
|
||||
secret_key: generate_frontend_secret(),
|
||||
},
|
||||
};
|
||||
let generated_config = toml::to_string(&config)?;
|
||||
println!("{generated_config}");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, ValueEnum)]
|
||||
enum PwhashAlgorithm {
|
||||
#[value(help = "Use this for your password")]
|
||||
Argon2,
|
||||
#[value(help = "Significantly faster algorithm, use for app tokens")]
|
||||
Pbkdf2,
|
||||
}
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct PwhashArgs {
|
||||
#[arg(long, short = 'a')]
|
||||
algorithm: PwhashAlgorithm,
|
||||
#[arg(
|
||||
long,
|
||||
short = 'r',
|
||||
help = "ONLY for pbkdf2: Number of rounds to calculate",
|
||||
default_value_t = 1000
|
||||
)]
|
||||
rounds: u32,
|
||||
}
|
||||
|
||||
pub fn cmd_pwhash(args: PwhashArgs) -> anyhow::Result<()> {
|
||||
println!("Enter your password:");
|
||||
let password = rpassword::read_password()?;
|
||||
let salt = SaltString::generate(OsRng);
|
||||
let password_hash = match args.algorithm {
|
||||
PwhashAlgorithm::Argon2 => argon2::Argon2::default()
|
||||
.hash_password(password.as_bytes(), &salt)
|
||||
.unwrap(),
|
||||
PwhashAlgorithm::Pbkdf2 => pbkdf2::Pbkdf2
|
||||
.hash_password_customized(
|
||||
password.as_bytes(),
|
||||
None,
|
||||
None,
|
||||
Params {
|
||||
rounds: args.rounds,
|
||||
..Default::default()
|
||||
},
|
||||
&salt,
|
||||
)
|
||||
.unwrap(),
|
||||
};
|
||||
println!("{password_hash}");
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user