mirror of
https://git.proxmox.com/git/proxmox-backup
synced 2025-05-28 18:20:27 +00:00
fix #4734: manager: add user tfa {list, delete} commands
Adds the commands proxmox-backup-manager user tfa list <userid> proxmox-backup-manager user tfa delete <userid> <id> Signed-off-by: Maximiliano Sandoval <m.sandoval@proxmox.com>
This commit is contained in:
parent
223842887f
commit
9c85840fe2
@ -69,7 +69,7 @@ async fn tfa_update_auth(
|
||||
},
|
||||
)]
|
||||
/// Add a TOTP secret to the user.
|
||||
fn list_user_tfa(userid: Userid) -> Result<Vec<methods::TypedTfaInfo>, Error> {
|
||||
pub fn list_user_tfa(userid: Userid) -> Result<Vec<methods::TypedTfaInfo>, Error> {
|
||||
let _lock = crate::config::tfa::read_lock()?;
|
||||
|
||||
methods::list_user_tfa(&crate::config::tfa::read()?, userid.as_str())
|
||||
@ -122,7 +122,7 @@ fn get_tfa_entry(userid: Userid, id: String) -> Result<methods::TypedTfaInfo, Er
|
||||
},
|
||||
)]
|
||||
/// Delete a single TFA entry.
|
||||
async fn delete_tfa(
|
||||
pub async fn delete_tfa(
|
||||
userid: Userid,
|
||||
id: String,
|
||||
password: Option<String>,
|
||||
|
@ -157,6 +157,40 @@ fn list_permissions(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Val
|
||||
Ok(Value::Null)
|
||||
}
|
||||
|
||||
#[api(
|
||||
input: {
|
||||
properties: {
|
||||
"output-format": {
|
||||
schema: OUTPUT_FORMAT,
|
||||
optional: true,
|
||||
},
|
||||
userid: {
|
||||
type: Userid,
|
||||
}
|
||||
},
|
||||
}
|
||||
)]
|
||||
/// List all tfa methods for a user.
|
||||
fn list_user_tfa(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Value, Error> {
|
||||
let output_format = get_output_format(¶m);
|
||||
|
||||
let info = &api2::access::tfa::API_METHOD_LIST_USER_TFA;
|
||||
let mut data = match info.handler {
|
||||
ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
let options = default_table_format_options()
|
||||
.column(ColumnConfig::new("id"))
|
||||
.column(ColumnConfig::new("type"))
|
||||
.column(ColumnConfig::new("description"))
|
||||
.column(ColumnConfig::new("created").renderer(pbs_tools::format::render_epoch));
|
||||
|
||||
format_and_print_result_full(&mut data, &info.returns, &output_format, &options);
|
||||
|
||||
Ok(Value::Null)
|
||||
}
|
||||
|
||||
pub fn user_commands() -> CommandLineInterface {
|
||||
let cmd_def = CliCommandMap::new()
|
||||
.insert("list", CliCommand::new(&API_METHOD_LIST_USERS))
|
||||
@ -196,6 +230,7 @@ pub fn user_commands() -> CommandLineInterface {
|
||||
.completion_cb("userid", pbs_config::user::complete_userid)
|
||||
.completion_cb("token-name", pbs_config::user::complete_token_name),
|
||||
)
|
||||
.insert("tfa", tfa_commands())
|
||||
.insert(
|
||||
"permissions",
|
||||
CliCommand::new(&API_METHOD_LIST_PERMISSIONS)
|
||||
@ -206,3 +241,21 @@ pub fn user_commands() -> CommandLineInterface {
|
||||
|
||||
cmd_def.into()
|
||||
}
|
||||
|
||||
fn tfa_commands() -> CommandLineInterface {
|
||||
CliCommandMap::new()
|
||||
.insert(
|
||||
"list",
|
||||
CliCommand::new(&API_METHOD_LIST_USER_TFA)
|
||||
.arg_param(&["userid"])
|
||||
.completion_cb("userid", pbs_config::user::complete_userid),
|
||||
)
|
||||
.insert(
|
||||
"delete",
|
||||
CliCommand::new(&api2::access::tfa::API_METHOD_DELETE_TFA)
|
||||
.arg_param(&["userid", "id"])
|
||||
.completion_cb("userid", pbs_config::user::complete_userid)
|
||||
.completion_cb("id", proxmox_backup::config::tfa::complete_tfa_id),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read, Seek, SeekFrom};
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
@ -302,3 +303,30 @@ impl proxmox_tfa::api::UserChallengeAccess for TfaUserChallengeData {
|
||||
TfaUserChallengeData::save(self)
|
||||
}
|
||||
}
|
||||
|
||||
// shell completion helper
|
||||
pub fn complete_tfa_id(_arg: &str, param: &HashMap<String, String>) -> Vec<String> {
|
||||
let mut results = Vec::new();
|
||||
|
||||
let data = match read() {
|
||||
Ok(data) => data,
|
||||
Err(_err) => return results,
|
||||
};
|
||||
let user = match param
|
||||
.get("userid")
|
||||
.and_then(|user_name| data.users.get(user_name))
|
||||
{
|
||||
Some(user) => user,
|
||||
None => return results,
|
||||
};
|
||||
|
||||
results.extend(user.totp.iter().map(|token| token.info.id.clone()));
|
||||
results.extend(user.u2f.iter().map(|token| token.info.id.clone()));
|
||||
results.extend(user.webauthn.iter().map(|token| token.info.id.clone()));
|
||||
results.extend(user.yubico.iter().map(|token| token.info.id.clone()));
|
||||
if user.recovery.is_some() {
|
||||
results.push("recovery".to_string());
|
||||
};
|
||||
|
||||
results
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user