use std::collections::BTreeMap;
use kanidm_proto::constants::*;
use kanidm_proto::internal::{CredentialStatus, IdentifyUserRequest, IdentifyUserResponse};
use kanidm_proto::v1::{AccountUnixExtend, Entry, SingleStringRequest, UatStatus};
use uuid::Uuid;
use crate::{ClientError, KanidmClient};
impl KanidmClient {
pub async fn idm_person_account_list(&self) -> Result<Vec<Entry>, ClientError> {
self.perform_get_request("/v1/person").await
}
pub async fn idm_person_account_get(&self, id: &str) -> Result<Option<Entry>, ClientError> {
self.perform_get_request(format!("/v1/person/{}", id).as_str())
.await
}
pub async fn idm_person_search(&self, id: &str) -> Result<Vec<Entry>, ClientError> {
self.perform_get_request(format!("/v1/person/_search/{}", id).as_str())
.await
}
pub async fn idm_person_account_create(
&self,
name: &str,
displayname: &str,
) -> Result<(), ClientError> {
let mut new_acct = Entry {
attrs: BTreeMap::new(),
};
new_acct
.attrs
.insert(ATTR_NAME.to_string(), vec![name.to_string()]);
new_acct
.attrs
.insert(ATTR_DISPLAYNAME.to_string(), vec![displayname.to_string()]);
self.perform_post_request("/v1/person", new_acct).await
}
pub async fn idm_person_account_update(
&self,
id: &str,
newname: Option<&str>,
displayname: Option<&str>,
legalname: Option<&str>,
mail: Option<&[String]>,
) -> Result<(), ClientError> {
let mut update_entry = Entry {
attrs: BTreeMap::new(),
};
if let Some(newname) = newname {
update_entry
.attrs
.insert(ATTR_NAME.to_string(), vec![newname.to_string()]);
}
if let Some(newdisplayname) = displayname {
update_entry.attrs.insert(
ATTR_DISPLAYNAME.to_string(),
vec![newdisplayname.to_string()],
);
}
if let Some(newlegalname) = legalname {
update_entry
.attrs
.insert(ATTR_LEGALNAME.to_string(), vec![newlegalname.to_string()]);
}
if let Some(mail) = mail {
update_entry
.attrs
.insert(ATTR_MAIL.to_string(), mail.to_vec());
}
self.perform_patch_request(format!("/v1/person/{}", id).as_str(), update_entry)
.await
}
pub async fn idm_person_account_delete(&self, id: &str) -> Result<(), ClientError> {
self.perform_delete_request(format!("/v1/person/{}", id).as_str())
.await
}
pub async fn idm_person_account_add_attr(
&self,
id: &str,
attr: &str,
values: &[&str],
) -> Result<(), ClientError> {
let msg: Vec<_> = values.iter().map(|v| (*v).to_string()).collect();
self.perform_post_request(format!("/v1/person/{}/_attr/{}", id, attr).as_str(), msg)
.await
}
pub async fn idm_person_account_set_attr(
&self,
id: &str,
attr: &str,
values: &[&str],
) -> Result<(), ClientError> {
let m: Vec<_> = values.iter().map(|v| (*v).to_string()).collect();
self.perform_put_request(format!("/v1/person/{}/_attr/{}", id, attr).as_str(), m)
.await
}
pub async fn idm_person_account_get_attr(
&self,
id: &str,
attr: &str,
) -> Result<Option<Vec<String>>, ClientError> {
self.perform_get_request(format!("/v1/person/{}/_attr/{}", id, attr).as_str())
.await
}
pub async fn idm_person_account_purge_attr(
&self,
id: &str,
attr: &str,
) -> Result<(), ClientError> {
self.perform_delete_request(format!("/v1/person/{}/_attr/{}", id, attr).as_str())
.await
}
pub async fn idm_person_account_get_credential_status(
&self,
id: &str,
) -> Result<CredentialStatus, ClientError> {
let res: Result<CredentialStatus, ClientError> = self
.perform_get_request(format!("/v1/person/{}/_credential/_status", id).as_str())
.await;
res.and_then(|cs| {
if cs.creds.is_empty() {
Err(ClientError::EmptyResponse)
} else {
Ok(cs)
}
})
}
pub async fn idm_person_account_primary_credential_set_password(
&self,
id: &str,
pw: &str,
) -> Result<(), ClientError> {
let (session_tok, status) = self.idm_account_credential_update_begin(id).await?;
trace!(?status);
let status = self
.idm_account_credential_update_set_password(&session_tok, pw)
.await?;
trace!(?status);
self.idm_account_credential_update_commit(&session_tok)
.await
}
pub async fn idm_person_account_post_ssh_pubkey(
&self,
id: &str,
tag: &str,
pubkey: &str,
) -> Result<(), ClientError> {
let sk = (tag.to_string(), pubkey.to_string());
self.perform_post_request(format!("/v1/person/{}/_ssh_pubkeys", id).as_str(), sk)
.await
}
pub async fn idm_person_account_delete_ssh_pubkey(
&self,
id: &str,
tag: &str,
) -> Result<(), ClientError> {
self.perform_delete_request(format!("/v1/person/{}/_ssh_pubkeys/{}", id, tag).as_str())
.await
}
pub async fn idm_person_account_unix_extend(
&self,
id: &str,
gidnumber: Option<u32>,
shell: Option<&str>,
) -> Result<(), ClientError> {
let ux = AccountUnixExtend {
shell: shell.map(str::to_string),
gidnumber,
};
self.perform_post_request(format!("/v1/person/{}/_unix", id).as_str(), ux)
.await
}
pub async fn idm_person_account_unix_cred_put(
&self,
id: &str,
cred: &str,
) -> Result<(), ClientError> {
let req = SingleStringRequest {
value: cred.to_string(),
};
self.perform_put_request(
["/v1/person/", id, "/_unix/_credential"].concat().as_str(),
req,
)
.await
}
pub async fn idm_person_account_unix_cred_delete(&self, id: &str) -> Result<(), ClientError> {
self.perform_delete_request(["/v1/person/", id, "/_unix/_credential"].concat().as_str())
.await
}
pub async fn idm_person_identify_user(
&self,
id: &str,
request: IdentifyUserRequest,
) -> Result<IdentifyUserResponse, ClientError> {
self.perform_post_request(
["/v1/person/", id, "/_identify_user"].concat().as_str(),
request,
)
.await
}
pub async fn idm_account_radius_credential_get(
&self,
id: &str,
) -> Result<Option<String>, ClientError> {
self.perform_get_request(format!("/v1/person/{}/_radius", id).as_str())
.await
}
pub async fn idm_account_radius_credential_regenerate(
&self,
id: &str,
) -> Result<String, ClientError> {
self.perform_post_request(format!("/v1/person/{}/_radius", id).as_str(), ())
.await
}
pub async fn idm_account_radius_credential_delete(&self, id: &str) -> Result<(), ClientError> {
self.perform_delete_request(format!("/v1/person/{}/_radius", id).as_str())
.await
}
pub async fn idm_account_list_user_auth_token(
&self,
id: &str,
) -> Result<Vec<UatStatus>, ClientError> {
self.perform_get_request(format!("/v1/account/{}/_user_auth_token", id).as_str())
.await
}
pub async fn idm_account_destroy_user_auth_token(
&self,
id: &str,
token_id: Uuid,
) -> Result<(), ClientError> {
self.perform_delete_request(
format!(
"/v1/account/{}/_user_auth_token/{}",
id,
&token_id.to_string()
)
.as_str(),
)
.await
}
pub async fn idm_person_certificate_list(&self, id: &str) -> Result<Vec<Entry>, ClientError> {
self.perform_get_request(format!("/v1/person/{}/_certificate", id).as_str())
.await
}
pub async fn idm_person_certificate_create(
&self,
id: &str,
pem_data: &str,
) -> Result<(), ClientError> {
let mut new_cert = Entry {
attrs: BTreeMap::new(),
};
new_cert
.attrs
.insert(ATTR_CERTIFICATE.to_string(), vec![pem_data.to_string()]);
self.perform_post_request(format!("/v1/person/{}/_certificate", id).as_str(), new_cert)
.await
}
}