CLI: Allow editing principal password

This commit is contained in:
Lennart
2025-04-26 10:52:23 +02:00
parent 6b9bd1226f
commit 4071ea4ff4
6 changed files with 68 additions and 22 deletions

View File

@@ -31,7 +31,7 @@ pub fn cmd_gen_config(_args: GenConfigArgs) -> anyhow::Result<()> {
path: "/etc/rustical/principals.toml".to_owned(),
}),
data_store: DataStoreConfig::Sqlite(SqliteDataStoreConfig {
db_url: "".to_owned(),
db_url: "/var/lib/rustical/db.sqlite3".to_owned(),
}),
tracing: TracingConfig::default(),
frontend: FrontendConfig {

View File

@@ -35,16 +35,28 @@ struct RemoveArgs {
id: String,
}
#[derive(Parser, Debug)]
struct EditArgs {
id: String,
#[arg(long, help = "Ask for password input")]
password: bool,
#[arg(
long,
help = "Remove password (If you only want to use OIDC for example)"
)]
remove_password: bool,
}
#[derive(Debug, Subcommand)]
enum Command {
List,
Create(CreateArgs),
Remove(RemoveArgs),
Edit(EditArgs),
}
pub async fn cmd_principals(args: PrincipalsArgs) -> anyhow::Result<()> {
let config: Config = Figment::new()
// TODO: What to do when config file does not exist?
.merge(Toml::file(&args.config_file))
.merge(Env::prefixed("RUSTICAL_").split("__"))
.extract()?;
@@ -85,14 +97,17 @@ pub async fn cmd_principals(args: PrincipalsArgs) -> anyhow::Result<()> {
None
};
user_store
.insert_principal(User {
id,
displayname: name,
principal_type: principal_type.unwrap_or_default(),
app_tokens: vec![],
password,
memberships: vec![],
})
.insert_principal(
User {
id,
displayname: name,
principal_type: principal_type.unwrap_or_default(),
app_tokens: vec![],
password,
memberships: vec![],
},
false,
)
.await?;
println!("Principal created");
}
@@ -100,6 +115,34 @@ pub async fn cmd_principals(args: PrincipalsArgs) -> anyhow::Result<()> {
user_store.remove_principal(&id).await?;
println!("Principal {id} removed");
}
Command::Edit(EditArgs {
id,
remove_password,
password,
}) => {
let mut principal = user_store
.get_principal(&id)
.await?
.unwrap_or_else(|| panic!("Principal {id} does not exist"));
if remove_password {
principal.password = None;
}
if password {
let salt = SaltString::generate(OsRng);
println!("Enter your password:");
let password = rpassword::read_password()?;
principal.password = Some(
argon2::Argon2::default()
.hash_password(password.as_bytes(), &salt)
.unwrap()
.to_string()
.into(),
)
}
user_store.insert_principal(principal, true).await?;
println!("Principal {id} updated");
}
}
Ok(())
}

View File

@@ -77,7 +77,6 @@ async fn main() -> Result<()> {
Some(Command::Principals(principals_args)) => cmd_principals(principals_args).await?,
None => {
let config: Config = Figment::new()
// TODO: What to do when config file does not exist?
.merge(Toml::file(&args.config_file))
.merge(Env::prefixed("RUSTICAL_").split("__"))
.extract()?;
@@ -196,6 +195,7 @@ mod tests {
async fn insert_principal(
&self,
_user: rustical_store::auth::User,
_overwrite: bool,
) -> Result<(), rustical_store::Error> {
Err(rustical_store::Error::Other(anyhow!("Not implemented")))
}