@ -3,13 +3,12 @@
|
||||
use anyhow::{bail, Error};
|
||||
use hex::FromHex;
|
||||
|
||||
use proxmox_router::{Router, RpcEnvironment, Permission};
|
||||
use proxmox_router::{Permission, Router, RpcEnvironment};
|
||||
use proxmox_schema::api;
|
||||
|
||||
use pbs_api_types::{
|
||||
Authid, AclListItem, Role,
|
||||
ACL_PATH_SCHEMA, PROXMOX_CONFIG_DIGEST_SCHEMA, PROXMOX_GROUP_ID_SCHEMA,
|
||||
ACL_PROPAGATE_SCHEMA, PRIV_SYS_AUDIT, PRIV_PERMISSIONS_MODIFY,
|
||||
AclListItem, Authid, Role, ACL_PATH_SCHEMA, ACL_PROPAGATE_SCHEMA, PRIV_PERMISSIONS_MODIFY,
|
||||
PRIV_SYS_AUDIT, PROXMOX_CONFIG_DIGEST_SCHEMA, PROXMOX_GROUP_ID_SCHEMA,
|
||||
};
|
||||
|
||||
use pbs_config::acl::AclTreeNode;
|
||||
@ -32,15 +31,18 @@ fn extract_acl_node_data(
|
||||
|
||||
for (user, roles) in &node.users {
|
||||
if let Some(auth_id_filter) = auth_id_filter {
|
||||
if !user.is_token()
|
||||
|| user.user() != auth_id_filter.user() {
|
||||
continue;
|
||||
if !user.is_token() || user.user() != auth_id_filter.user() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (role, propagate) in roles {
|
||||
list.push(AclListItem {
|
||||
path: if path.is_empty() { String::from("/") } else { path.to_string() },
|
||||
path: if path.is_empty() {
|
||||
String::from("/")
|
||||
} else {
|
||||
path.to_string()
|
||||
},
|
||||
propagate: *propagate,
|
||||
ugid_type: String::from("user"),
|
||||
ugid: user.to_string(),
|
||||
@ -55,7 +57,11 @@ fn extract_acl_node_data(
|
||||
|
||||
for (role, propagate) in roles {
|
||||
list.push(AclListItem {
|
||||
path: if path.is_empty() { String::from("/") } else { path.to_string() },
|
||||
path: if path.is_empty() {
|
||||
String::from("/")
|
||||
} else {
|
||||
path.to_string()
|
||||
},
|
||||
propagate: *propagate,
|
||||
ugid_type: String::from("group"),
|
||||
ugid: group.to_string(),
|
||||
@ -201,8 +207,10 @@ pub fn update_acl(
|
||||
} else if auth_id.user() != current_auth_id.user() {
|
||||
bail!("Unprivileged users can only set ACL items for their own API tokens.");
|
||||
}
|
||||
},
|
||||
None => { bail!("Unprivileged user needs to provide auth_id to update ACL item."); },
|
||||
}
|
||||
None => {
|
||||
bail!("Unprivileged user needs to provide auth_id to update ACL item.");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -222,18 +230,26 @@ pub fn update_acl(
|
||||
if let Some(ref _group) = group {
|
||||
bail!("parameter 'group' - groups are currently not supported.");
|
||||
} else if let Some(ref auth_id) = auth_id {
|
||||
if !delete { // Note: we allow to delete non-existent users
|
||||
if !delete {
|
||||
// Note: we allow to delete non-existent users
|
||||
let user_cfg = pbs_config::user::cached_config()?;
|
||||
if user_cfg.sections.get(&auth_id.to_string()).is_none() {
|
||||
bail!(format!("no such {}.",
|
||||
if auth_id.is_token() { "API token" } else { "user" }));
|
||||
bail!(format!(
|
||||
"no such {}.",
|
||||
if auth_id.is_token() {
|
||||
"API token"
|
||||
} else {
|
||||
"user"
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bail!("missing 'userid' or 'group' parameter.");
|
||||
}
|
||||
|
||||
if !delete { // Note: we allow to delete entries with invalid path
|
||||
if !delete {
|
||||
// Note: we allow to delete entries with invalid path
|
||||
pbs_config::acl::check_acl_path(&path)?;
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
//! List Authentication domains/realms
|
||||
|
||||
use anyhow::{Error};
|
||||
use anyhow::Error;
|
||||
use serde_json::{json, Value};
|
||||
|
||||
use proxmox_router::{Router, RpcEnvironment, Permission};
|
||||
use proxmox_router::{Permission, Router, RpcEnvironment};
|
||||
use proxmox_schema::api;
|
||||
|
||||
use pbs_api_types::BasicRealmInfo;
|
||||
@ -50,5 +50,4 @@ fn list_domains(mut rpcenv: &mut dyn RpcEnvironment) -> Result<Vec<BasicRealmInf
|
||||
Ok(list)
|
||||
}
|
||||
|
||||
pub const ROUTER: Router = Router::new()
|
||||
.get(&API_METHOD_LIST_DOMAINS);
|
||||
pub const ROUTER: Router = Router::new().get(&API_METHOD_LIST_DOMAINS);
|
||||
|
@ -6,19 +6,19 @@ use serde_json::{json, Value};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
|
||||
use proxmox_sys::sortable;
|
||||
use proxmox_router::{
|
||||
http_err, list_subdirs_api_method, Router, RpcEnvironment, SubdirMap, Permission,
|
||||
http_err, list_subdirs_api_method, Permission, Router, RpcEnvironment, SubdirMap,
|
||||
};
|
||||
use proxmox_schema::api;
|
||||
use proxmox_sys::sortable;
|
||||
|
||||
use pbs_api_types::{
|
||||
Userid, Authid, PASSWORD_SCHEMA, ACL_PATH_SCHEMA,
|
||||
PRIVILEGES, PRIV_PERMISSIONS_MODIFY, PRIV_SYS_AUDIT,
|
||||
Authid, Userid, ACL_PATH_SCHEMA, PASSWORD_SCHEMA, PRIVILEGES, PRIV_PERMISSIONS_MODIFY,
|
||||
PRIV_SYS_AUDIT,
|
||||
};
|
||||
use pbs_tools::ticket::{self, Empty, Ticket};
|
||||
use pbs_config::acl::AclTreeNode;
|
||||
use pbs_config::CachedUserInfo;
|
||||
use pbs_tools::ticket::{self, Empty, Ticket};
|
||||
|
||||
use crate::auth_helpers::*;
|
||||
use crate::config::tfa::TfaChallenge;
|
||||
@ -193,10 +193,11 @@ pub fn create_ticket(
|
||||
tfa_challenge: Option<String>,
|
||||
rpcenv: &mut dyn RpcEnvironment,
|
||||
) -> Result<Value, Error> {
|
||||
|
||||
use proxmox_rest_server::RestEnvironment;
|
||||
|
||||
let env: &RestEnvironment = rpcenv.as_any().downcast_ref::<RestEnvironment>()
|
||||
let env: &RestEnvironment = rpcenv
|
||||
.as_any()
|
||||
.downcast_ref::<RestEnvironment>()
|
||||
.ok_or_else(|| format_err!("detected worng RpcEnvironment type"))?;
|
||||
|
||||
match authenticate_user(&username, &password, path, privs, port, tfa_challenge) {
|
||||
@ -340,7 +341,7 @@ pub fn list_permissions(
|
||||
} else {
|
||||
bail!("not allowed to list permissions of {}", auth_id);
|
||||
}
|
||||
},
|
||||
}
|
||||
None => current_auth_id,
|
||||
};
|
||||
|
||||
|
@ -4,31 +4,35 @@ use std::convert::TryFrom;
|
||||
use anyhow::{bail, format_err, Error};
|
||||
use serde_json::{json, Value};
|
||||
|
||||
use proxmox_sys::sortable;
|
||||
use proxmox_router::{
|
||||
http_err, list_subdirs_api_method, Router, RpcEnvironment, SubdirMap, Permission,
|
||||
http_err, list_subdirs_api_method, Permission, Router, RpcEnvironment, SubdirMap,
|
||||
};
|
||||
use proxmox_schema::api;
|
||||
use proxmox_sys::sortable;
|
||||
|
||||
use proxmox_openid::{OpenIdAuthenticator, OpenIdConfig};
|
||||
|
||||
use pbs_api_types::{
|
||||
OpenIdRealmConfig, User, Userid,
|
||||
EMAIL_SCHEMA, FIRST_NAME_SCHEMA, LAST_NAME_SCHEMA, OPENID_DEFAILT_SCOPE_LIST,
|
||||
REALM_ID_SCHEMA,
|
||||
OpenIdRealmConfig, User, Userid, EMAIL_SCHEMA, FIRST_NAME_SCHEMA, LAST_NAME_SCHEMA,
|
||||
OPENID_DEFAILT_SCOPE_LIST, REALM_ID_SCHEMA,
|
||||
};
|
||||
use pbs_buildcfg::PROXMOX_BACKUP_RUN_DIR_M;
|
||||
use pbs_tools::ticket::Ticket;
|
||||
|
||||
use pbs_config::CachedUserInfo;
|
||||
use pbs_config::open_backup_lockfile;
|
||||
use pbs_config::CachedUserInfo;
|
||||
|
||||
use crate::auth_helpers::*;
|
||||
use crate::server::ticket::ApiTicket;
|
||||
|
||||
fn openid_authenticator(realm_config: &OpenIdRealmConfig, redirect_url: &str) -> Result<OpenIdAuthenticator, Error> {
|
||||
|
||||
let scopes: Vec<String> = realm_config.scopes.as_deref().unwrap_or(OPENID_DEFAILT_SCOPE_LIST)
|
||||
fn openid_authenticator(
|
||||
realm_config: &OpenIdRealmConfig,
|
||||
redirect_url: &str,
|
||||
) -> Result<OpenIdAuthenticator, Error> {
|
||||
let scopes: Vec<String> = realm_config
|
||||
.scopes
|
||||
.as_deref()
|
||||
.unwrap_or(OPENID_DEFAILT_SCOPE_LIST)
|
||||
.split(|c: char| c == ',' || c == ';' || char::is_ascii_whitespace(&c))
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(String::from)
|
||||
@ -37,11 +41,10 @@ fn openid_authenticator(realm_config: &OpenIdRealmConfig, redirect_url: &str) ->
|
||||
let mut acr_values = None;
|
||||
if let Some(ref list) = realm_config.acr_values {
|
||||
acr_values = Some(
|
||||
list
|
||||
.split(|c: char| c == ',' || c == ';' || char::is_ascii_whitespace(&c))
|
||||
list.split(|c: char| c == ',' || c == ';' || char::is_ascii_whitespace(&c))
|
||||
.filter(|s| !s.is_empty())
|
||||
.map(String::from)
|
||||
.collect()
|
||||
.collect(),
|
||||
);
|
||||
}
|
||||
|
||||
@ -105,7 +108,9 @@ pub fn openid_login(
|
||||
) -> Result<Value, Error> {
|
||||
use proxmox_rest_server::RestEnvironment;
|
||||
|
||||
let env: &RestEnvironment = rpcenv.as_any().downcast_ref::<RestEnvironment>()
|
||||
let env: &RestEnvironment = rpcenv
|
||||
.as_any()
|
||||
.downcast_ref::<RestEnvironment>()
|
||||
.ok_or_else(|| format_err!("detected worng RpcEnvironment type"))?;
|
||||
|
||||
let user_info = CachedUserInfo::new()?;
|
||||
@ -113,7 +118,6 @@ pub fn openid_login(
|
||||
let mut tested_username = None;
|
||||
|
||||
let result = proxmox_lang::try_block!({
|
||||
|
||||
let (realm, private_auth_state) =
|
||||
OpenIdAuthenticator::verify_public_auth_state(PROXMOX_BACKUP_RUN_DIR_M!(), &state)?;
|
||||
|
||||
@ -157,13 +161,19 @@ pub fn openid_login(
|
||||
use pbs_config::user;
|
||||
let _lock = open_backup_lockfile(user::USER_CFG_LOCKFILE, None, true)?;
|
||||
|
||||
let firstname = info["given_name"].as_str().map(|n| n.to_string())
|
||||
let firstname = info["given_name"]
|
||||
.as_str()
|
||||
.map(|n| n.to_string())
|
||||
.filter(|n| FIRST_NAME_SCHEMA.parse_simple_value(n).is_ok());
|
||||
|
||||
let lastname = info["family_name"].as_str().map(|n| n.to_string())
|
||||
let lastname = info["family_name"]
|
||||
.as_str()
|
||||
.map(|n| n.to_string())
|
||||
.filter(|n| LAST_NAME_SCHEMA.parse_simple_value(n).is_ok());
|
||||
|
||||
let email = info["email"].as_str().map(|n| n.to_string())
|
||||
let email = info["email"]
|
||||
.as_str()
|
||||
.map(|n| n.to_string())
|
||||
.filter(|n| EMAIL_SCHEMA.parse_simple_value(n).is_ok());
|
||||
|
||||
let user = User {
|
||||
@ -206,7 +216,7 @@ pub fn openid_login(
|
||||
if let Err(ref err) = result {
|
||||
let msg = err.to_string();
|
||||
env.log_failed_auth(tested_username, &msg);
|
||||
return Err(http_err!(UNAUTHORIZED, "{}", msg))
|
||||
return Err(http_err!(UNAUTHORIZED, "{}", msg));
|
||||
}
|
||||
|
||||
result
|
||||
@ -240,7 +250,6 @@ fn openid_auth_url(
|
||||
redirect_url: String,
|
||||
_rpcenv: &mut dyn RpcEnvironment,
|
||||
) -> Result<String, Error> {
|
||||
|
||||
let (domains, _digest) = pbs_config::domains::config()?;
|
||||
let config: OpenIdRealmConfig = domains.lookup("openid", &realm)?;
|
||||
|
||||
|
@ -7,7 +7,7 @@ use serde_json::{json, Value};
|
||||
use proxmox_router::{Permission, Router};
|
||||
use proxmox_schema::api;
|
||||
|
||||
use pbs_api_types::{Role, SINGLE_LINE_COMMENT_SCHEMA, PRIVILEGES};
|
||||
use pbs_api_types::{Role, PRIVILEGES, SINGLE_LINE_COMMENT_SCHEMA};
|
||||
use pbs_config::acl::ROLE_NAMES;
|
||||
|
||||
#[api(
|
||||
@ -56,5 +56,4 @@ fn list_roles() -> Result<Value, Error> {
|
||||
Ok(list.into())
|
||||
}
|
||||
|
||||
pub const ROUTER: Router = Router::new()
|
||||
.get(&API_METHOD_LIST_ROLES);
|
||||
pub const ROUTER: Router = Router::new().get(&API_METHOD_LIST_ROLES);
|
||||
|
@ -1,19 +1,18 @@
|
||||
//! User Management
|
||||
|
||||
use anyhow::{bail, format_err, Error};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use hex::FromHex;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
use std::collections::HashMap;
|
||||
use hex::FromHex;
|
||||
|
||||
use proxmox_router::{ApiMethod, Router, RpcEnvironment, SubdirMap, Permission};
|
||||
use proxmox_router::{ApiMethod, Permission, Router, RpcEnvironment, SubdirMap};
|
||||
use proxmox_schema::api;
|
||||
|
||||
use pbs_api_types::{
|
||||
PROXMOX_CONFIG_DIGEST_SCHEMA, SINGLE_LINE_COMMENT_SCHEMA, Authid,
|
||||
Tokenname, UserWithTokens, Userid, User, UserUpdater, ApiToken,
|
||||
ENABLE_USER_SCHEMA, EXPIRE_USER_SCHEMA, PBS_PASSWORD_SCHEMA,
|
||||
PRIV_SYS_AUDIT, PRIV_PERMISSIONS_MODIFY,
|
||||
ApiToken, Authid, Tokenname, User, UserUpdater, UserWithTokens, Userid, ENABLE_USER_SCHEMA,
|
||||
EXPIRE_USER_SCHEMA, PBS_PASSWORD_SCHEMA, PRIV_PERMISSIONS_MODIFY, PRIV_SYS_AUDIT,
|
||||
PROXMOX_CONFIG_DIGEST_SCHEMA, SINGLE_LINE_COMMENT_SCHEMA,
|
||||
};
|
||||
use pbs_config::token_shadow;
|
||||
|
||||
@ -59,7 +58,6 @@ pub fn list_users(
|
||||
_info: &ApiMethod,
|
||||
mut rpcenv: &mut dyn RpcEnvironment,
|
||||
) -> Result<Vec<UserWithTokens>, Error> {
|
||||
|
||||
let (config, digest) = pbs_config::user::config()?;
|
||||
|
||||
let auth_id: Authid = rpcenv
|
||||
@ -74,41 +72,34 @@ pub fn list_users(
|
||||
let top_level_privs = user_info.lookup_privs(&auth_id, &["access", "users"]);
|
||||
let top_level_allowed = (top_level_privs & PRIV_SYS_AUDIT) != 0;
|
||||
|
||||
let filter_by_privs = |user: &User| {
|
||||
top_level_allowed || user.userid == *userid
|
||||
};
|
||||
let filter_by_privs = |user: &User| top_level_allowed || user.userid == *userid;
|
||||
|
||||
|
||||
let list:Vec<User> = config.convert_to_typed_array("user")?;
|
||||
let list: Vec<User> = config.convert_to_typed_array("user")?;
|
||||
|
||||
rpcenv["digest"] = hex::encode(&digest).into();
|
||||
|
||||
let iter = list.into_iter().filter(filter_by_privs);
|
||||
let list = if include_tokens {
|
||||
let tokens: Vec<ApiToken> = config.convert_to_typed_array("token")?;
|
||||
let mut user_to_tokens = tokens
|
||||
.into_iter()
|
||||
.fold(
|
||||
HashMap::new(),
|
||||
|mut map: HashMap<Userid, Vec<ApiToken>>, token: ApiToken| {
|
||||
let mut user_to_tokens = tokens.into_iter().fold(
|
||||
HashMap::new(),
|
||||
|mut map: HashMap<Userid, Vec<ApiToken>>, token: ApiToken| {
|
||||
if token.tokenid.is_token() {
|
||||
map
|
||||
.entry(token.tokenid.user().clone())
|
||||
map.entry(token.tokenid.user().clone())
|
||||
.or_default()
|
||||
.push(token);
|
||||
}
|
||||
map
|
||||
});
|
||||
iter
|
||||
.map(|user: User| {
|
||||
let mut user = new_user_with_tokens(user);
|
||||
user.tokens = user_to_tokens.remove(&user.userid).unwrap_or_default();
|
||||
user
|
||||
})
|
||||
.collect()
|
||||
},
|
||||
);
|
||||
iter.map(|user: User| {
|
||||
let mut user = new_user_with_tokens(user);
|
||||
user.tokens = user_to_tokens.remove(&user.userid).unwrap_or_default();
|
||||
user
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
iter.map(new_user_with_tokens)
|
||||
.collect()
|
||||
iter.map(new_user_with_tokens).collect()
|
||||
};
|
||||
|
||||
Ok(list)
|
||||
@ -136,14 +127,17 @@ pub fn list_users(
|
||||
pub fn create_user(
|
||||
password: Option<String>,
|
||||
config: User,
|
||||
rpcenv: &mut dyn RpcEnvironment
|
||||
rpcenv: &mut dyn RpcEnvironment,
|
||||
) -> Result<(), Error> {
|
||||
|
||||
let _lock = pbs_config::user::lock_config()?;
|
||||
|
||||
let (mut section_config, _digest) = pbs_config::user::config()?;
|
||||
|
||||
if section_config.sections.get(config.userid.as_str()).is_some() {
|
||||
if section_config
|
||||
.sections
|
||||
.get(config.userid.as_str())
|
||||
.is_some()
|
||||
{
|
||||
bail!("user '{}' already exists.", config.userid);
|
||||
}
|
||||
|
||||
@ -194,7 +188,7 @@ pub fn read_user(userid: Userid, mut rpcenv: &mut dyn RpcEnvironment) -> Result<
|
||||
|
||||
#[api()]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all="kebab-case")]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum DeletableProperty {
|
||||
/// Delete the comment property.
|
||||
@ -253,7 +247,6 @@ pub fn update_user(
|
||||
digest: Option<String>,
|
||||
rpcenv: &mut dyn RpcEnvironment,
|
||||
) -> Result<(), Error> {
|
||||
|
||||
let _lock = pbs_config::user::lock_config()?;
|
||||
|
||||
let (mut config, expected_digest) = pbs_config::user::config()?;
|
||||
@ -306,11 +299,19 @@ pub fn update_user(
|
||||
}
|
||||
|
||||
if let Some(firstname) = update.firstname {
|
||||
data.firstname = if firstname.is_empty() { None } else { Some(firstname) };
|
||||
data.firstname = if firstname.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(firstname)
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(lastname) = update.lastname {
|
||||
data.lastname = if lastname.is_empty() { None } else { Some(lastname) };
|
||||
data.lastname = if lastname.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(lastname)
|
||||
};
|
||||
}
|
||||
if let Some(email) = update.email {
|
||||
data.email = if email.is_empty() { None } else { Some(email) };
|
||||
@ -345,10 +346,9 @@ pub fn update_user(
|
||||
)]
|
||||
/// Remove a user from the configuration file.
|
||||
pub fn delete_user(userid: Userid, digest: Option<String>) -> Result<(), Error> {
|
||||
|
||||
let _lock = pbs_config::user::lock_config()?;
|
||||
let _tfa_lock = crate::config::tfa::write_lock()?;
|
||||
|
||||
|
||||
let (mut config, expected_digest) = pbs_config::user::config()?;
|
||||
|
||||
if let Some(ref digest) = digest {
|
||||
@ -357,7 +357,9 @@ pub fn delete_user(userid: Userid, digest: Option<String>) -> Result<(), Error>
|
||||
}
|
||||
|
||||
match config.sections.get(userid.as_str()) {
|
||||
Some(_) => { config.sections.remove(userid.as_str()); },
|
||||
Some(_) => {
|
||||
config.sections.remove(userid.as_str());
|
||||
}
|
||||
None => bail!("user '{}' does not exist.", userid),
|
||||
}
|
||||
|
||||
@ -365,7 +367,7 @@ pub fn delete_user(userid: Userid, digest: Option<String>) -> Result<(), Error>
|
||||
|
||||
let authenticator = crate::auth::lookup_authenticator(userid.realm())?;
|
||||
match authenticator.remove_password(userid.name()) {
|
||||
Ok(()) => {},
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
eprintln!(
|
||||
"error removing password after deleting user {:?}: {}",
|
||||
@ -417,7 +419,6 @@ pub fn read_token(
|
||||
_info: &ApiMethod,
|
||||
mut rpcenv: &mut dyn RpcEnvironment,
|
||||
) -> Result<ApiToken, Error> {
|
||||
|
||||
let (config, digest) = pbs_config::user::config()?;
|
||||
|
||||
let tokenid = Authid::from((userid, Some(token_name)));
|
||||
@ -483,7 +484,6 @@ pub fn generate_token(
|
||||
expire: Option<i64>,
|
||||
digest: Option<String>,
|
||||
) -> Result<Value, Error> {
|
||||
|
||||
let _lock = pbs_config::user::lock_config()?;
|
||||
|
||||
let (mut config, expected_digest) = pbs_config::user::config()?;
|
||||
@ -497,7 +497,11 @@ pub fn generate_token(
|
||||
let tokenid_string = tokenid.to_string();
|
||||
|
||||
if config.sections.get(&tokenid_string).is_some() {
|
||||
bail!("token '{}' for user '{}' already exists.", token_name.as_str(), userid);
|
||||
bail!(
|
||||
"token '{}' for user '{}' already exists.",
|
||||
token_name.as_str(),
|
||||
userid
|
||||
);
|
||||
}
|
||||
|
||||
let secret = format!("{:x}", proxmox_uuid::Uuid::generate());
|
||||
@ -564,7 +568,6 @@ pub fn update_token(
|
||||
expire: Option<i64>,
|
||||
digest: Option<String>,
|
||||
) -> Result<(), Error> {
|
||||
|
||||
let _lock = pbs_config::user::lock_config()?;
|
||||
|
||||
let (mut config, expected_digest) = pbs_config::user::config()?;
|
||||
@ -632,7 +635,6 @@ pub fn delete_token(
|
||||
token_name: Tokenname,
|
||||
digest: Option<String>,
|
||||
) -> Result<(), Error> {
|
||||
|
||||
let _lock = pbs_config::user::lock_config()?;
|
||||
|
||||
let (mut config, expected_digest) = pbs_config::user::config()?;
|
||||
@ -646,8 +648,14 @@ pub fn delete_token(
|
||||
let tokenid_string = tokenid.to_string();
|
||||
|
||||
match config.sections.get(&tokenid_string) {
|
||||
Some(_) => { config.sections.remove(&tokenid_string); },
|
||||
None => bail!("token '{}' of user '{}' does not exist.", token_name.as_str(), userid),
|
||||
Some(_) => {
|
||||
config.sections.remove(&tokenid_string);
|
||||
}
|
||||
None => bail!(
|
||||
"token '{}' of user '{}' does not exist.",
|
||||
token_name.as_str(),
|
||||
userid
|
||||
),
|
||||
}
|
||||
|
||||
token_shadow::delete_secret(&tokenid)?;
|
||||
@ -664,7 +672,7 @@ pub fn delete_token(
|
||||
}
|
||||
)]
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all="kebab-case")]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
/// A Token Entry that contains the token-name
|
||||
pub struct TokenApiEntry {
|
||||
/// The Token name
|
||||
@ -699,20 +707,16 @@ pub fn list_tokens(
|
||||
_info: &ApiMethod,
|
||||
mut rpcenv: &mut dyn RpcEnvironment,
|
||||
) -> Result<Vec<TokenApiEntry>, Error> {
|
||||
|
||||
let (config, digest) = pbs_config::user::config()?;
|
||||
|
||||
let list:Vec<ApiToken> = config.convert_to_typed_array("token")?;
|
||||
let list: Vec<ApiToken> = config.convert_to_typed_array("token")?;
|
||||
|
||||
rpcenv["digest"] = hex::encode(&digest).into();
|
||||
|
||||
let filter_by_owner = |token: ApiToken| {
|
||||
if token.tokenid.is_token() && token.tokenid.user() == &userid {
|
||||
let token_name = token.tokenid.tokenname().unwrap().to_owned();
|
||||
Some(TokenApiEntry {
|
||||
token_name,
|
||||
token,
|
||||
})
|
||||
Some(TokenApiEntry { token_name, token })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@ -733,9 +737,7 @@ const TOKEN_ROUTER: Router = Router::new()
|
||||
.get(&API_METHOD_LIST_TOKENS)
|
||||
.match_all("token-name", &TOKEN_ITEM_ROUTER);
|
||||
|
||||
const USER_SUBDIRS: SubdirMap = &[
|
||||
("token", &TOKEN_ROUTER),
|
||||
];
|
||||
const USER_SUBDIRS: SubdirMap = &[("token", &TOKEN_ROUTER)];
|
||||
|
||||
const USER_ROUTER: Router = Router::new()
|
||||
.get(&API_METHOD_READ_USER)
|
||||
|
Reference in New Issue
Block a user