mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-24 04:57:00 +01:00
Cleanup and improve client error handling
This commit is contained in:
parent
c4805d2915
commit
217e3455a2
|
@ -23,7 +23,7 @@ impl KanidmAsyncClient {
|
||||||
// format doesn't work in async ?!
|
// format doesn't work in async ?!
|
||||||
// let dest = format!("{}{}", self.addr, dest);
|
// let dest = format!("{}{}", self.addr, dest);
|
||||||
|
|
||||||
let req_string = serde_json::to_string(&request).unwrap();
|
let req_string = serde_json::to_string(&request).map_err(ClientError::JSONEncode)?;
|
||||||
|
|
||||||
let response = self
|
let response = self
|
||||||
.client
|
.client
|
||||||
|
@ -34,21 +34,28 @@ impl KanidmAsyncClient {
|
||||||
.await
|
.await
|
||||||
.map_err(ClientError::Transport)?;
|
.map_err(ClientError::Transport)?;
|
||||||
|
|
||||||
let opid = response.headers().get(KOPID);
|
let opid = response
|
||||||
debug!(
|
.headers()
|
||||||
"opid -> {:?}",
|
.get(KOPID)
|
||||||
opid.expect("Missing opid? Refusing to proceed ...")
|
.and_then(|hv| hv.to_str().ok().map(|s| s.to_string()))
|
||||||
);
|
.unwrap_or_else(|| "missing_kopid".to_string());
|
||||||
|
debug!("opid -> {:?}", opid);
|
||||||
|
|
||||||
match response.status() {
|
match response.status() {
|
||||||
reqwest::StatusCode::OK => {}
|
reqwest::StatusCode::OK => {}
|
||||||
unexpect => return Err(ClientError::Http(unexpect, response.json().await.ok())),
|
unexpect => {
|
||||||
|
return Err(ClientError::Http(
|
||||||
|
unexpect,
|
||||||
|
response.json().await.ok(),
|
||||||
|
opid,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO #253: What about errors
|
response
|
||||||
let r: T = response.json().await.unwrap();
|
.json()
|
||||||
|
.await
|
||||||
Ok(r)
|
.map_err(|e| ClientError::JSONDecode(e, opid))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn perform_put_request<R: Serialize, T: DeserializeOwned>(
|
async fn perform_put_request<R: Serialize, T: DeserializeOwned>(
|
||||||
|
@ -61,7 +68,7 @@ impl KanidmAsyncClient {
|
||||||
// format doesn't work in async ?!
|
// format doesn't work in async ?!
|
||||||
// let dest = format!("{}{}", self.addr, dest);
|
// let dest = format!("{}{}", self.addr, dest);
|
||||||
|
|
||||||
let req_string = serde_json::to_string(&request).unwrap();
|
let req_string = serde_json::to_string(&request).map_err(ClientError::JSONEncode)?;
|
||||||
|
|
||||||
let response = self
|
let response = self
|
||||||
.client
|
.client
|
||||||
|
@ -72,21 +79,29 @@ impl KanidmAsyncClient {
|
||||||
.await
|
.await
|
||||||
.map_err(ClientError::Transport)?;
|
.map_err(ClientError::Transport)?;
|
||||||
|
|
||||||
let opid = response.headers().get(KOPID);
|
let opid = response
|
||||||
debug!(
|
.headers()
|
||||||
"opid -> {:?}",
|
.get(KOPID)
|
||||||
opid.expect("Missing opid? Refusing to proceed ...")
|
.and_then(|hv| hv.to_str().ok().map(|s| s.to_string()))
|
||||||
);
|
.unwrap_or_else(|| "missing_kopid".to_string());
|
||||||
|
|
||||||
|
debug!("opid -> {:?}", opid);
|
||||||
|
|
||||||
match response.status() {
|
match response.status() {
|
||||||
reqwest::StatusCode::OK => {}
|
reqwest::StatusCode::OK => {}
|
||||||
unexpect => return Err(ClientError::Http(unexpect, response.json().await.ok())),
|
unexpect => {
|
||||||
|
return Err(ClientError::Http(
|
||||||
|
unexpect,
|
||||||
|
response.json().await.ok(),
|
||||||
|
opid,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO #253: What about errors
|
response
|
||||||
let r: T = response.json().await.unwrap();
|
.json()
|
||||||
|
.await
|
||||||
Ok(r)
|
.map_err(|e| ClientError::JSONDecode(e, opid))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn perform_get_request<T: DeserializeOwned>(&self, dest: &str) -> Result<T, ClientError> {
|
async fn perform_get_request<T: DeserializeOwned>(&self, dest: &str) -> Result<T, ClientError> {
|
||||||
|
@ -100,21 +115,29 @@ impl KanidmAsyncClient {
|
||||||
.await
|
.await
|
||||||
.map_err(ClientError::Transport)?;
|
.map_err(ClientError::Transport)?;
|
||||||
|
|
||||||
let opid = response.headers().get(KOPID);
|
let opid = response
|
||||||
debug!(
|
.headers()
|
||||||
"opid -> {:?}",
|
.get(KOPID)
|
||||||
opid.expect("Missing opid? Refusing to proceed ...")
|
.and_then(|hv| hv.to_str().ok().map(|s| s.to_string()))
|
||||||
);
|
.unwrap_or_else(|| "missing_kopid".to_string());
|
||||||
|
|
||||||
|
debug!("opid -> {:?}", opid);
|
||||||
|
|
||||||
match response.status() {
|
match response.status() {
|
||||||
reqwest::StatusCode::OK => {}
|
reqwest::StatusCode::OK => {}
|
||||||
unexpect => return Err(ClientError::Http(unexpect, response.json().await.ok())),
|
unexpect => {
|
||||||
|
return Err(ClientError::Http(
|
||||||
|
unexpect,
|
||||||
|
response.json().await.ok(),
|
||||||
|
opid,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO #253: What about errors
|
response
|
||||||
let r: T = response.json().await.unwrap();
|
.json()
|
||||||
|
.await
|
||||||
Ok(r)
|
.map_err(|e| ClientError::JSONDecode(e, opid))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn perform_delete_request(&self, dest: &str) -> Result<bool, ClientError> {
|
async fn perform_delete_request(&self, dest: &str) -> Result<bool, ClientError> {
|
||||||
|
@ -126,20 +149,28 @@ impl KanidmAsyncClient {
|
||||||
.await
|
.await
|
||||||
.map_err(ClientError::Transport)?;
|
.map_err(ClientError::Transport)?;
|
||||||
|
|
||||||
let opid = response.headers().get(KOPID);
|
let opid = response
|
||||||
debug!(
|
.headers()
|
||||||
"opid -> {:?}",
|
.get(KOPID)
|
||||||
opid.expect("Missing opid? Refusing to proceed ...")
|
.and_then(|hv| hv.to_str().ok().map(|s| s.to_string()))
|
||||||
);
|
.unwrap_or_else(|| "missing_kopid".to_string());
|
||||||
|
debug!("opid -> {:?}", opid);
|
||||||
|
|
||||||
match response.status() {
|
match response.status() {
|
||||||
reqwest::StatusCode::OK => {}
|
reqwest::StatusCode::OK => {}
|
||||||
unexpect => return Err(ClientError::Http(unexpect, response.json().await.ok())),
|
unexpect => {
|
||||||
|
return Err(ClientError::Http(
|
||||||
|
unexpect,
|
||||||
|
response.json().await.ok(),
|
||||||
|
opid,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let r: bool = response.json().await.unwrap();
|
response
|
||||||
|
.json()
|
||||||
Ok(r)
|
.await
|
||||||
|
.map_err(|e| ClientError::JSONDecode(e, opid))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn auth_step_init(&self, ident: &str) -> Result<AuthState, ClientError> {
|
pub async fn auth_step_init(&self, ident: &str) -> Result<AuthState, ClientError> {
|
||||||
|
@ -205,17 +236,37 @@ impl KanidmAsyncClient {
|
||||||
let whoami_dest = [self.addr.as_str(), "/v1/self"].concat();
|
let whoami_dest = [self.addr.as_str(), "/v1/self"].concat();
|
||||||
// format!("{}/v1/self", self.addr);
|
// format!("{}/v1/self", self.addr);
|
||||||
debug!("{:?}", whoami_dest);
|
debug!("{:?}", whoami_dest);
|
||||||
let response = self.client.get(whoami_dest.as_str()).send().await.unwrap();
|
let response = self
|
||||||
|
.client
|
||||||
|
.get(whoami_dest.as_str())
|
||||||
|
.send()
|
||||||
|
.await
|
||||||
|
.map_err(ClientError::Transport)?;
|
||||||
|
|
||||||
|
let opid = response
|
||||||
|
.headers()
|
||||||
|
.get(KOPID)
|
||||||
|
.and_then(|hv| hv.to_str().ok().map(|s| s.to_string()))
|
||||||
|
.unwrap_or_else(|| "missing_kopid".to_string());
|
||||||
|
debug!("opid -> {:?}", opid);
|
||||||
|
|
||||||
match response.status() {
|
match response.status() {
|
||||||
// Continue to process.
|
// Continue to process.
|
||||||
reqwest::StatusCode::OK => {}
|
reqwest::StatusCode::OK => {}
|
||||||
reqwest::StatusCode::UNAUTHORIZED => return Ok(None),
|
reqwest::StatusCode::UNAUTHORIZED => return Ok(None),
|
||||||
unexpect => return Err(ClientError::Http(unexpect, response.json().await.ok())),
|
unexpect => {
|
||||||
|
return Err(ClientError::Http(
|
||||||
|
unexpect,
|
||||||
|
response.json().await.ok(),
|
||||||
|
opid,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let r: WhoamiResponse =
|
let r: WhoamiResponse = response
|
||||||
serde_json::from_str(response.text().await.unwrap().as_str()).unwrap();
|
.json()
|
||||||
|
.await
|
||||||
|
.map_err(|e| ClientError::JSONDecode(e, opid))?;
|
||||||
|
|
||||||
Ok(Some((r.youare, r.uat)))
|
Ok(Some((r.youare, r.uat)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
#![warn(unused_extern_crates)]
|
#![warn(unused_extern_crates)]
|
||||||
|
#![deny(clippy::unwrap_used)]
|
||||||
|
#![deny(clippy::expect_used)]
|
||||||
|
#![deny(clippy::panic)]
|
||||||
|
#![deny(clippy::unreachable)]
|
||||||
|
#![deny(clippy::await_holding_lock)]
|
||||||
|
#![deny(clippy::needless_pass_by_value)]
|
||||||
|
#![deny(clippy::trivially_copy_pass_by_ref)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
@ -8,6 +15,7 @@ use reqwest::header::CONTENT_TYPE;
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
|
use serde_json::error::Error as SerdeJsonError;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fs::{metadata, File, Metadata};
|
use std::fs::{metadata, File, Metadata};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
@ -35,12 +43,13 @@ pub const KOPID: &str = "X-KANIDM-OPID";
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ClientError {
|
pub enum ClientError {
|
||||||
Unauthorized,
|
Unauthorized,
|
||||||
Http(reqwest::StatusCode, Option<OperationError>),
|
Http(reqwest::StatusCode, Option<OperationError>, String),
|
||||||
Transport(reqwest::Error),
|
Transport(reqwest::Error),
|
||||||
AuthenticationFailed,
|
AuthenticationFailed,
|
||||||
JsonParse,
|
|
||||||
EmptyResponse,
|
EmptyResponse,
|
||||||
TOTPVerifyFailed(Uuid, TOTPSecret),
|
TOTPVerifyFailed(Uuid, TOTPSecret),
|
||||||
|
JSONDecode(reqwest::Error, String),
|
||||||
|
JSONEncode(SerdeJsonError),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
@ -341,7 +350,7 @@ impl KanidmClient {
|
||||||
) -> Result<T, ClientError> {
|
) -> Result<T, ClientError> {
|
||||||
let dest = format!("{}{}", self.addr, dest);
|
let dest = format!("{}{}", self.addr, dest);
|
||||||
|
|
||||||
let req_string = serde_json::to_string(&request).unwrap();
|
let req_string = serde_json::to_string(&request).map_err(ClientError::JSONEncode)?;
|
||||||
|
|
||||||
let response = self
|
let response = self
|
||||||
.client
|
.client
|
||||||
|
@ -351,21 +360,21 @@ impl KanidmClient {
|
||||||
.send()
|
.send()
|
||||||
.map_err(ClientError::Transport)?;
|
.map_err(ClientError::Transport)?;
|
||||||
|
|
||||||
let opid = response.headers().get(KOPID);
|
let opid = response
|
||||||
debug!(
|
.headers()
|
||||||
"opid -> {:?}",
|
.get(KOPID)
|
||||||
opid.expect("Missing opid? Refusing to proceed ...")
|
.and_then(|hv| hv.to_str().ok().map(|s| s.to_string()))
|
||||||
);
|
.unwrap_or_else(|| "missing_kopid".to_string());
|
||||||
|
debug!("opid -> {:?}", opid);
|
||||||
|
|
||||||
match response.status() {
|
match response.status() {
|
||||||
reqwest::StatusCode::OK => {}
|
reqwest::StatusCode::OK => {}
|
||||||
unexpect => return Err(ClientError::Http(unexpect, response.json().ok())),
|
unexpect => return Err(ClientError::Http(unexpect, response.json().ok(), opid)),
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO #253: What about errors
|
response
|
||||||
let r: T = response.json().unwrap();
|
.json()
|
||||||
|
.map_err(|e| ClientError::JSONDecode(e, opid))
|
||||||
Ok(r)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn perform_put_request<R: Serialize, T: DeserializeOwned>(
|
fn perform_put_request<R: Serialize, T: DeserializeOwned>(
|
||||||
|
@ -375,7 +384,7 @@ impl KanidmClient {
|
||||||
) -> Result<T, ClientError> {
|
) -> Result<T, ClientError> {
|
||||||
let dest = format!("{}{}", self.addr, dest);
|
let dest = format!("{}{}", self.addr, dest);
|
||||||
|
|
||||||
let req_string = serde_json::to_string(&request).unwrap();
|
let req_string = serde_json::to_string(&request).map_err(ClientError::JSONEncode)?;
|
||||||
|
|
||||||
let response = self
|
let response = self
|
||||||
.client
|
.client
|
||||||
|
@ -385,21 +394,21 @@ impl KanidmClient {
|
||||||
.send()
|
.send()
|
||||||
.map_err(ClientError::Transport)?;
|
.map_err(ClientError::Transport)?;
|
||||||
|
|
||||||
let opid = response.headers().get(KOPID);
|
let opid = response
|
||||||
debug!(
|
.headers()
|
||||||
"opid -> {:?}",
|
.get(KOPID)
|
||||||
opid.expect("Missing opid? Refusing to proceed ...")
|
.and_then(|hv| hv.to_str().ok().map(|s| s.to_string()))
|
||||||
);
|
.unwrap_or_else(|| "missing_kopid".to_string());
|
||||||
|
debug!("opid -> {:?}", opid);
|
||||||
|
|
||||||
match response.status() {
|
match response.status() {
|
||||||
reqwest::StatusCode::OK => {}
|
reqwest::StatusCode::OK => {}
|
||||||
unexpect => return Err(ClientError::Http(unexpect, response.json().ok())),
|
unexpect => return Err(ClientError::Http(unexpect, response.json().ok(), opid)),
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO #253: What about errors
|
response
|
||||||
let r: T = response.json().unwrap();
|
.json()
|
||||||
|
.map_err(|e| ClientError::JSONDecode(e, opid))
|
||||||
Ok(r)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn perform_get_request<T: DeserializeOwned>(&self, dest: &str) -> Result<T, ClientError> {
|
fn perform_get_request<T: DeserializeOwned>(&self, dest: &str) -> Result<T, ClientError> {
|
||||||
|
@ -410,21 +419,21 @@ impl KanidmClient {
|
||||||
.send()
|
.send()
|
||||||
.map_err(ClientError::Transport)?;
|
.map_err(ClientError::Transport)?;
|
||||||
|
|
||||||
let opid = response.headers().get(KOPID);
|
let opid = response
|
||||||
debug!(
|
.headers()
|
||||||
"opid -> {:?}",
|
.get(KOPID)
|
||||||
opid.expect("Missing opid? Refusing to proceed ...")
|
.and_then(|hv| hv.to_str().ok().map(|s| s.to_string()))
|
||||||
);
|
.unwrap_or_else(|| "missing_kopid".to_string());
|
||||||
|
debug!("opid -> {:?}", opid);
|
||||||
|
|
||||||
match response.status() {
|
match response.status() {
|
||||||
reqwest::StatusCode::OK => {}
|
reqwest::StatusCode::OK => {}
|
||||||
unexpect => return Err(ClientError::Http(unexpect, response.json().ok())),
|
unexpect => return Err(ClientError::Http(unexpect, response.json().ok(), opid)),
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO #253: What about errors
|
response
|
||||||
let r: T = response.json().unwrap();
|
.json()
|
||||||
|
.map_err(|e| ClientError::JSONDecode(e, opid))
|
||||||
Ok(r)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn perform_delete_request(&self, dest: &str) -> Result<bool, ClientError> {
|
fn perform_delete_request(&self, dest: &str) -> Result<bool, ClientError> {
|
||||||
|
@ -435,36 +444,50 @@ impl KanidmClient {
|
||||||
.send()
|
.send()
|
||||||
.map_err(ClientError::Transport)?;
|
.map_err(ClientError::Transport)?;
|
||||||
|
|
||||||
let opid = response.headers().get(KOPID);
|
let opid = response
|
||||||
debug!(
|
.headers()
|
||||||
"opid -> {:?}",
|
.get(KOPID)
|
||||||
opid.expect("Missing opid? Refusing to proceed ...")
|
.and_then(|hv| hv.to_str().ok().map(|s| s.to_string()))
|
||||||
);
|
.unwrap_or_else(|| "missing_kopid".to_string());
|
||||||
|
debug!("opid -> {:?}", opid);
|
||||||
|
|
||||||
match response.status() {
|
match response.status() {
|
||||||
reqwest::StatusCode::OK => {}
|
reqwest::StatusCode::OK => {}
|
||||||
unexpect => return Err(ClientError::Http(unexpect, response.json().ok())),
|
unexpect => return Err(ClientError::Http(unexpect, response.json().ok(), opid)),
|
||||||
}
|
}
|
||||||
|
|
||||||
let r: bool = response.json().unwrap();
|
response
|
||||||
|
.json()
|
||||||
Ok(r)
|
.map_err(|e| ClientError::JSONDecode(e, opid))
|
||||||
}
|
}
|
||||||
|
|
||||||
// whoami
|
// whoami
|
||||||
// Can't use generic get due to possible un-auth case.
|
// Can't use generic get due to possible un-auth case.
|
||||||
pub fn whoami(&self) -> Result<Option<(Entry, UserAuthToken)>, ClientError> {
|
pub fn whoami(&self) -> Result<Option<(Entry, UserAuthToken)>, ClientError> {
|
||||||
let whoami_dest = format!("{}/v1/self", self.addr);
|
let whoami_dest = format!("{}/v1/self", self.addr);
|
||||||
let response = self.client.get(whoami_dest.as_str()).send().unwrap();
|
let response = self
|
||||||
|
.client
|
||||||
|
.get(whoami_dest.as_str())
|
||||||
|
.send()
|
||||||
|
.map_err(ClientError::Transport)?;
|
||||||
|
|
||||||
|
let opid = response
|
||||||
|
.headers()
|
||||||
|
.get(KOPID)
|
||||||
|
.and_then(|hv| hv.to_str().ok().map(|s| s.to_string()))
|
||||||
|
.unwrap_or_else(|| "missing_kopid".to_string());
|
||||||
|
debug!("opid -> {:?}", opid);
|
||||||
|
|
||||||
match response.status() {
|
match response.status() {
|
||||||
// Continue to process.
|
// Continue to process.
|
||||||
reqwest::StatusCode::OK => {}
|
reqwest::StatusCode::OK => {}
|
||||||
reqwest::StatusCode::UNAUTHORIZED => return Ok(None),
|
reqwest::StatusCode::UNAUTHORIZED => return Ok(None),
|
||||||
unexpect => return Err(ClientError::Http(unexpect, response.json().ok())),
|
unexpect => return Err(ClientError::Http(unexpect, response.json().ok(), opid)),
|
||||||
}
|
}
|
||||||
|
|
||||||
let r: WhoamiResponse = serde_json::from_str(response.text().unwrap().as_str()).unwrap();
|
let r: WhoamiResponse = response
|
||||||
|
.json()
|
||||||
|
.map_err(|e| ClientError::JSONDecode(e, opid))?;
|
||||||
|
|
||||||
Ok(Some((r.youare, r.uat)))
|
Ok(Some((r.youare, r.uat)))
|
||||||
}
|
}
|
||||||
|
@ -608,12 +631,12 @@ impl KanidmClient {
|
||||||
self.perform_get_request(format!("/v1/group/{}/_attr/member", id).as_str())
|
self.perform_get_request(format!("/v1/group/{}/_attr/member", id).as_str())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn idm_group_set_members(&self, id: &str, members: Vec<&str>) -> Result<bool, ClientError> {
|
pub fn idm_group_set_members(&self, id: &str, members: &[&str]) -> Result<bool, ClientError> {
|
||||||
let m: Vec<_> = members.iter().map(|v| (*v).to_string()).collect();
|
let m: Vec<_> = members.iter().map(|v| (*v).to_string()).collect();
|
||||||
self.perform_put_request(format!("/v1/group/{}/_attr/member", id).as_str(), m)
|
self.perform_put_request(format!("/v1/group/{}/_attr/member", id).as_str(), m)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn idm_group_add_members(&self, id: &str, members: Vec<&str>) -> Result<bool, ClientError> {
|
pub fn idm_group_add_members(&self, id: &str, members: &[&str]) -> Result<bool, ClientError> {
|
||||||
let m: Vec<_> = members.iter().map(|v| (*v).to_string()).collect();
|
let m: Vec<_> = members.iter().map(|v| (*v).to_string()).collect();
|
||||||
self.perform_post_request(format!("/v1/group/{}/_attr/member", id).as_str(), m)
|
self.perform_post_request(format!("/v1/group/{}/_attr/member", id).as_str(), m)
|
||||||
}
|
}
|
||||||
|
@ -881,7 +904,12 @@ impl KanidmClient {
|
||||||
// pub fn idm_domain_get_attr
|
// pub fn idm_domain_get_attr
|
||||||
pub fn idm_domain_get_ssid(&self, id: &str) -> Result<String, ClientError> {
|
pub fn idm_domain_get_ssid(&self, id: &str) -> Result<String, ClientError> {
|
||||||
self.perform_get_request(format!("/v1/domain/{}/_attr/domain_ssid", id).as_str())
|
self.perform_get_request(format!("/v1/domain/{}/_attr/domain_ssid", id).as_str())
|
||||||
.and_then(|mut r: Vec<String>| Ok(r.pop().unwrap()))
|
.and_then(|mut r: Vec<String>|
|
||||||
|
// Get the first result
|
||||||
|
r.pop()
|
||||||
|
.ok_or(
|
||||||
|
ClientError::EmptyResponse
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub fn idm_domain_put_attr
|
// pub fn idm_domain_put_attr
|
||||||
|
|
|
@ -63,9 +63,7 @@ fn create_user(rsclient: &KanidmClient, id: &str, group_name: &str) -> () {
|
||||||
None => rsclient.idm_group_create(&group_name).unwrap(),
|
None => rsclient.idm_group_create(&group_name).unwrap(),
|
||||||
};
|
};
|
||||||
|
|
||||||
rsclient
|
rsclient.idm_group_add_members(&group_name, &[id]).unwrap();
|
||||||
.idm_group_add_members(&group_name, vec![id])
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_attr_writable(rsclient: &KanidmClient, id: &str, attr: &str) -> Option<bool> {
|
fn is_attr_writable(rsclient: &KanidmClient, id: &str, attr: &str) -> Option<bool> {
|
||||||
|
@ -115,7 +113,7 @@ fn is_attr_writable(rsclient: &KanidmClient, id: &str, attr: &str) -> Option<boo
|
||||||
fn add_all_attrs(mut rsclient: &mut KanidmClient, id: &str, group_name: &str) {
|
fn add_all_attrs(mut rsclient: &mut KanidmClient, id: &str, group_name: &str) {
|
||||||
// Extend with posix attrs to test read attr: gidnumber and loginshell
|
// Extend with posix attrs to test read attr: gidnumber and loginshell
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_add_members("idm_admins", vec!["admin"])
|
.idm_group_add_members("idm_admins", &["admin"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
rsclient
|
rsclient
|
||||||
.idm_account_unix_extend(id, None, Some(&"/bin/bash"))
|
.idm_account_unix_extend(id, None, Some(&"/bin/bash"))
|
||||||
|
@ -157,10 +155,10 @@ fn create_user_with_all_attrs(
|
||||||
|
|
||||||
fn login_account(rsclient: &mut KanidmClient, id: &str) -> () {
|
fn login_account(rsclient: &mut KanidmClient, id: &str) -> () {
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_add_members("idm_people_account_password_import_priv", vec!["admin"])
|
.idm_group_add_members("idm_people_account_password_import_priv", &["admin"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_add_members("idm_people_extend_priv", vec!["admin"])
|
.idm_group_add_members("idm_people_extend_priv", &["admin"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
rsclient
|
rsclient
|
||||||
|
@ -215,7 +213,7 @@ fn test_modify_group(rsclient: &KanidmClient, group_names: &[&str], is_modificab
|
||||||
["description", "name"].iter().for_each(|attr| {
|
["description", "name"].iter().for_each(|attr| {
|
||||||
assert!(is_attr_writable(&rsclient, group, attr).unwrap() == is_modificable)
|
assert!(is_attr_writable(&rsclient, group, attr).unwrap() == is_modificable)
|
||||||
});
|
});
|
||||||
assert!(rsclient.idm_group_add_members(group, vec!["test"]).is_ok() == is_modificable);
|
assert!(rsclient.idm_group_add_members(group, &["test"]).is_ok() == is_modificable);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,7 +324,7 @@ fn test_default_entries_rbac_group_managers() {
|
||||||
|
|
||||||
rsclient.idm_group_create("test_group").unwrap();
|
rsclient.idm_group_create("test_group").unwrap();
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_add_members("test_group", vec!["test"])
|
.idm_group_add_members("test_group", &["test"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(is_attr_writable(&rsclient, "test_group", "description").unwrap());
|
assert!(is_attr_writable(&rsclient, "test_group", "description").unwrap());
|
||||||
});
|
});
|
||||||
|
@ -588,7 +586,7 @@ fn test_default_entries_rbac_anonymous_entry() {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
create_user_with_all_attrs(&mut rsclient, "test", Some("test_group"));
|
create_user_with_all_attrs(&mut rsclient, "test", Some("test_group"));
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_add_members("test_group", vec!["anonymous"])
|
.idm_group_add_members("test_group", &["anonymous"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
add_all_attrs(&mut rsclient, "anonymous", "test_group");
|
add_all_attrs(&mut rsclient, "anonymous", "test_group");
|
||||||
|
|
||||||
|
|
|
@ -251,14 +251,14 @@ fn test_server_rest_group_lifecycle() {
|
||||||
|
|
||||||
// Add a member.
|
// Add a member.
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_add_members("demo_group", vec!["admin"])
|
.idm_group_add_members("demo_group", &["admin"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let members = rsclient.idm_group_get_members("demo_group").unwrap();
|
let members = rsclient.idm_group_get_members("demo_group").unwrap();
|
||||||
assert!(members == Some(vec!["admin@example.com".to_string()]));
|
assert!(members == Some(vec!["admin@example.com".to_string()]));
|
||||||
|
|
||||||
// Set the list of members
|
// Set the list of members
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_set_members("demo_group", vec!["admin", "demo_group"])
|
.idm_group_set_members("demo_group", &["admin", "demo_group"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let members = rsclient.idm_group_get_members("demo_group").unwrap();
|
let members = rsclient.idm_group_get_members("demo_group").unwrap();
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -395,7 +395,7 @@ fn test_server_rest_account_lifecycle() {
|
||||||
// To enable the admin to actually make some of these changes, we have
|
// To enable the admin to actually make some of these changes, we have
|
||||||
// to make them a people admin. NOT recommended in production!
|
// to make them a people admin. NOT recommended in production!
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_add_members("idm_account_write_priv", vec!["admin"])
|
.idm_group_add_members("idm_account_write_priv", &["admin"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Create a new account
|
// Create a new account
|
||||||
|
@ -499,7 +499,7 @@ fn test_server_rest_posix_lifecycle() {
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
// Not recommended in production!
|
// Not recommended in production!
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_add_members("idm_admins", vec!["admin"])
|
.idm_group_add_members("idm_admins", &["admin"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Create a new account
|
// Create a new account
|
||||||
|
@ -517,7 +517,7 @@ fn test_server_rest_posix_lifecycle() {
|
||||||
// Extend the group with posix attrs
|
// Extend the group with posix attrs
|
||||||
rsclient.idm_group_create("posix_group").unwrap();
|
rsclient.idm_group_create("posix_group").unwrap();
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_add_members("posix_group", vec!["posix_account"])
|
.idm_group_add_members("posix_group", &["posix_account"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
rsclient.idm_group_unix_extend("posix_group", None).unwrap();
|
rsclient.idm_group_unix_extend("posix_group", None).unwrap();
|
||||||
|
|
||||||
|
@ -576,7 +576,7 @@ fn test_server_rest_posix_auth_lifecycle() {
|
||||||
|
|
||||||
// Not recommended in production!
|
// Not recommended in production!
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_add_members("idm_admins", vec!["admin"])
|
.idm_group_add_members("idm_admins", &["admin"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Setup a unix user
|
// Setup a unix user
|
||||||
|
@ -634,7 +634,7 @@ fn test_server_rest_recycle_lifecycle() {
|
||||||
|
|
||||||
// Not recommended in production!
|
// Not recommended in production!
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_add_members("idm_admins", vec!["admin"])
|
.idm_group_add_members("idm_admins", &["admin"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Setup a unix user
|
// Setup a unix user
|
||||||
|
@ -674,10 +674,10 @@ fn test_server_rest_account_import_password() {
|
||||||
// To enable the admin to actually make some of these changes, we have
|
// To enable the admin to actually make some of these changes, we have
|
||||||
// to make them a password import admin. NOT recommended in production!
|
// to make them a password import admin. NOT recommended in production!
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_add_members("idm_people_account_password_import_priv", vec!["admin"])
|
.idm_group_add_members("idm_people_account_password_import_priv", &["admin"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_add_members("idm_people_extend_priv", vec!["admin"])
|
.idm_group_add_members("idm_people_extend_priv", &["admin"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Create a new account
|
// Create a new account
|
||||||
|
@ -718,7 +718,7 @@ fn test_server_rest_totp_auth_lifecycle() {
|
||||||
|
|
||||||
// Not recommended in production!
|
// Not recommended in production!
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_add_members("idm_admins", vec!["admin"])
|
.idm_group_add_members("idm_admins", &["admin"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Create a new account
|
// Create a new account
|
||||||
|
|
|
@ -171,70 +171,82 @@ impl AccountOpt {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
client
|
if let Err(e) = client.idm_account_primary_credential_set_password(
|
||||||
.idm_account_primary_credential_set_password(
|
|
||||||
acsopt.aopts.account_id.as_str(),
|
acsopt.aopts.account_id.as_str(),
|
||||||
password.as_str(),
|
password.as_str(),
|
||||||
)
|
) {
|
||||||
.unwrap();
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AccountCredential::GeneratePassword(acsopt) => {
|
AccountCredential::GeneratePassword(acsopt) => {
|
||||||
let client = acsopt.copt.to_client();
|
let client = acsopt.copt.to_client();
|
||||||
|
|
||||||
let npw = client
|
match client.idm_account_primary_credential_set_generated(
|
||||||
.idm_account_primary_credential_set_generated(
|
|
||||||
acsopt.aopts.account_id.as_str(),
|
acsopt.aopts.account_id.as_str(),
|
||||||
)
|
) {
|
||||||
.unwrap();
|
Ok(npw) => {
|
||||||
println!(
|
println!(
|
||||||
"Generated password for {}: {}",
|
"Generated password for {}: {}",
|
||||||
acsopt.aopts.account_id, npw
|
acsopt.aopts.account_id, npw
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}, // end AccountOpt::Credential
|
}, // end AccountOpt::Credential
|
||||||
AccountOpt::Radius(aropt) => match aropt {
|
AccountOpt::Radius(aropt) => match aropt {
|
||||||
AccountRadius::Show(aopt) => {
|
AccountRadius::Show(aopt) => {
|
||||||
let client = aopt.copt.to_client();
|
let client = aopt.copt.to_client();
|
||||||
|
|
||||||
let rcred = client
|
let rcred =
|
||||||
.idm_account_radius_credential_get(aopt.aopts.account_id.as_str())
|
client.idm_account_radius_credential_get(aopt.aopts.account_id.as_str());
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
match rcred {
|
match rcred {
|
||||||
Some(s) => println!("Radius secret: {}", s),
|
Ok(Some(s)) => println!("Radius secret: {}", s),
|
||||||
None => println!("NO Radius secret"),
|
Ok(None) => println!("NO Radius secret"),
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AccountRadius::Generate(aopt) => {
|
AccountRadius::Generate(aopt) => {
|
||||||
let client = aopt.copt.to_client();
|
let client = aopt.copt.to_client();
|
||||||
client
|
if let Err(e) = client
|
||||||
.idm_account_radius_credential_regenerate(aopt.aopts.account_id.as_str())
|
.idm_account_radius_credential_regenerate(aopt.aopts.account_id.as_str())
|
||||||
.unwrap();
|
{
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AccountRadius::Delete(aopt) => {
|
AccountRadius::Delete(aopt) => {
|
||||||
let client = aopt.copt.to_client();
|
let client = aopt.copt.to_client();
|
||||||
client
|
if let Err(e) =
|
||||||
.idm_account_radius_credential_delete(aopt.aopts.account_id.as_str())
|
client.idm_account_radius_credential_delete(aopt.aopts.account_id.as_str())
|
||||||
.unwrap();
|
{
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, // end AccountOpt::Radius
|
}, // end AccountOpt::Radius
|
||||||
AccountOpt::Posix(apopt) => match apopt {
|
AccountOpt::Posix(apopt) => match apopt {
|
||||||
AccountPosix::Show(aopt) => {
|
AccountPosix::Show(aopt) => {
|
||||||
let client = aopt.copt.to_client();
|
let client = aopt.copt.to_client();
|
||||||
let token = client
|
match client.idm_account_unix_token_get(aopt.aopts.account_id.as_str()) {
|
||||||
.idm_account_unix_token_get(aopt.aopts.account_id.as_str())
|
Ok(token) => println!("{}", token),
|
||||||
.unwrap();
|
Err(e) => {
|
||||||
println!("{}", token);
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AccountPosix::Set(aopt) => {
|
AccountPosix::Set(aopt) => {
|
||||||
let client = aopt.copt.to_client();
|
let client = aopt.copt.to_client();
|
||||||
client
|
if let Err(e) = client.idm_account_unix_extend(
|
||||||
.idm_account_unix_extend(
|
|
||||||
aopt.aopts.account_id.as_str(),
|
aopt.aopts.account_id.as_str(),
|
||||||
aopt.gidnumber,
|
aopt.gidnumber,
|
||||||
aopt.shell.as_deref(),
|
aopt.shell.as_deref(),
|
||||||
)
|
) {
|
||||||
.unwrap();
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AccountPosix::SetPassword(aopt) => {
|
AccountPosix::SetPassword(aopt) => {
|
||||||
let client = aopt.copt.to_client();
|
let client = aopt.copt.to_client();
|
||||||
|
@ -246,77 +258,74 @@ impl AccountOpt {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
client
|
if let Err(e) = client.idm_account_unix_cred_put(
|
||||||
.idm_account_unix_cred_put(
|
|
||||||
aopt.aopts.account_id.as_str(),
|
aopt.aopts.account_id.as_str(),
|
||||||
password.as_str(),
|
password.as_str(),
|
||||||
)
|
) {
|
||||||
.unwrap();
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, // end AccountOpt::Posix
|
}, // end AccountOpt::Posix
|
||||||
AccountOpt::Ssh(asopt) => match asopt {
|
AccountOpt::Ssh(asopt) => match asopt {
|
||||||
AccountSsh::List(aopt) => {
|
AccountSsh::List(aopt) => {
|
||||||
let client = aopt.copt.to_client();
|
let client = aopt.copt.to_client();
|
||||||
|
|
||||||
let pkeys = client
|
match client.idm_account_get_ssh_pubkeys(aopt.aopts.account_id.as_str()) {
|
||||||
.idm_account_get_ssh_pubkeys(aopt.aopts.account_id.as_str())
|
Ok(pkeys) => pkeys.iter().for_each(|pkey| println!("{}", pkey)),
|
||||||
.unwrap();
|
Err(e) => {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
for pkey in pkeys {
|
}
|
||||||
println!("{}", pkey)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AccountSsh::Add(aopt) => {
|
AccountSsh::Add(aopt) => {
|
||||||
let client = aopt.copt.to_client();
|
let client = aopt.copt.to_client();
|
||||||
client
|
if let Err(e) = client.idm_account_post_ssh_pubkey(
|
||||||
.idm_account_post_ssh_pubkey(
|
|
||||||
aopt.aopts.account_id.as_str(),
|
aopt.aopts.account_id.as_str(),
|
||||||
aopt.tag.as_str(),
|
aopt.tag.as_str(),
|
||||||
aopt.pubkey.as_str(),
|
aopt.pubkey.as_str(),
|
||||||
)
|
) {
|
||||||
.unwrap();
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AccountSsh::Delete(aopt) => {
|
AccountSsh::Delete(aopt) => {
|
||||||
let client = aopt.copt.to_client();
|
let client = aopt.copt.to_client();
|
||||||
client
|
if let Err(e) = client.idm_account_delete_ssh_pubkey(
|
||||||
.idm_account_delete_ssh_pubkey(
|
|
||||||
aopt.aopts.account_id.as_str(),
|
aopt.aopts.account_id.as_str(),
|
||||||
aopt.tag.as_str(),
|
aopt.tag.as_str(),
|
||||||
)
|
) {
|
||||||
.unwrap();
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, // end AccountOpt::Ssh
|
}, // end AccountOpt::Ssh
|
||||||
AccountOpt::List(copt) => {
|
AccountOpt::List(copt) => {
|
||||||
let client = copt.to_client();
|
let client = copt.to_client();
|
||||||
let r = client.idm_account_list().unwrap();
|
match client.idm_account_list() {
|
||||||
for e in r {
|
Ok(r) => r.iter().for_each(|ent| println!("{}", ent)),
|
||||||
println!("{}", e);
|
Err(e) => eprintln!("Error -> {:?}", e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AccountOpt::Get(aopt) => {
|
AccountOpt::Get(aopt) => {
|
||||||
let client = aopt.copt.to_client();
|
let client = aopt.copt.to_client();
|
||||||
let e = client
|
match client.idm_account_get(aopt.aopts.account_id.as_str()) {
|
||||||
.idm_account_get(aopt.aopts.account_id.as_str())
|
Ok(Some(e)) => println!("{}", e),
|
||||||
.unwrap();
|
Ok(None) => println!("No matching entries"),
|
||||||
match e {
|
Err(e) => eprintln!("Error -> {:?}", e),
|
||||||
Some(e) => println!("{}", e),
|
|
||||||
None => println!("No matching entries"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AccountOpt::Delete(aopt) => {
|
AccountOpt::Delete(aopt) => {
|
||||||
let client = aopt.copt.to_client();
|
let client = aopt.copt.to_client();
|
||||||
client
|
if let Err(e) = client.idm_account_delete(aopt.aopts.account_id.as_str()) {
|
||||||
.idm_account_delete(aopt.aopts.account_id.as_str())
|
eprintln!("Error -> {:?}", e)
|
||||||
.unwrap();
|
}
|
||||||
}
|
}
|
||||||
AccountOpt::Create(acopt) => {
|
AccountOpt::Create(acopt) => {
|
||||||
let client = acopt.copt.to_client();
|
let client = acopt.copt.to_client();
|
||||||
client
|
if let Err(e) = client.idm_account_create(
|
||||||
.idm_account_create(
|
|
||||||
acopt.aopts.account_id.as_str(),
|
acopt.aopts.account_id.as_str(),
|
||||||
acopt.display_name.as_str(),
|
acopt.display_name.as_str(),
|
||||||
)
|
) {
|
||||||
.unwrap();
|
eprintln!("Error -> {:?}", e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,35 +27,54 @@ impl CommonOpt {
|
||||||
let config_path: String = shellexpand::tilde("~/.config/kanidm").into_owned();
|
let config_path: String = shellexpand::tilde("~/.config/kanidm").into_owned();
|
||||||
|
|
||||||
debug!("Attempting to use config {}", "/etc/kanidm/config");
|
debug!("Attempting to use config {}", "/etc/kanidm/config");
|
||||||
let client_builder = KanidmClientBuilder::new()
|
let client_builder = match KanidmClientBuilder::new()
|
||||||
.read_options_from_optional_config("/etc/kanidm/config")
|
.read_options_from_optional_config("/etc/kanidm/config")
|
||||||
.and_then(|cb| {
|
.and_then(|cb| {
|
||||||
debug!("Attempting to use config {}", config_path);
|
debug!("Attempting to use config {}", config_path);
|
||||||
cb.read_options_from_optional_config(config_path)
|
cb.read_options_from_optional_config(config_path)
|
||||||
})
|
}) {
|
||||||
.expect("Failed to parse config (if present)");
|
Ok(c) => c,
|
||||||
|
Err(e) => {
|
||||||
|
error!("Failed to parse config (if present) -- {:?}", e);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let client_builder = match &self.addr {
|
let client_builder = match &self.addr {
|
||||||
Some(a) => client_builder.address(a.to_string()),
|
Some(a) => client_builder.address(a.to_string()),
|
||||||
None => client_builder,
|
None => client_builder,
|
||||||
};
|
};
|
||||||
|
|
||||||
let ca_path: Option<&str> = self.ca_path.as_ref().map(|p| p.to_str().unwrap());
|
let ca_path: Option<&str> = self.ca_path.as_ref().map(|p| p.to_str()).flatten();
|
||||||
let client_builder = match ca_path {
|
let client_builder = match ca_path {
|
||||||
Some(p) => client_builder
|
Some(p) => match client_builder.add_root_certificate_filepath(p) {
|
||||||
.add_root_certificate_filepath(p)
|
Ok(cb) => cb,
|
||||||
.expect("Failed to access CA file"),
|
Err(e) => {
|
||||||
|
error!("Failed to add ca certificate -- {:?}", e);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
},
|
||||||
None => client_builder,
|
None => client_builder,
|
||||||
};
|
};
|
||||||
|
|
||||||
let client = client_builder
|
let client = match client_builder.build() {
|
||||||
.build()
|
Ok(c) => c,
|
||||||
.expect("Failed to build client instance");
|
Err(e) => {
|
||||||
|
error!("Failed to build client instance -- {:?}", e);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let r = if self.username == "anonymous" {
|
let r = if self.username == "anonymous" {
|
||||||
client.auth_anonymous()
|
client.auth_anonymous()
|
||||||
} else {
|
} else {
|
||||||
let password = rpassword::prompt_password_stderr("Enter password: ").unwrap();
|
let password = match rpassword::prompt_password_stderr("Enter password: ") {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(e) => {
|
||||||
|
error!("Failed to create password prompt -- {:?}", e);
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
client.auth_simple_password(self.username.as_str(), password.as_str())
|
client.auth_simple_password(self.username.as_str(), password.as_str())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -70,29 +70,38 @@ impl GroupOpt {
|
||||||
match self {
|
match self {
|
||||||
GroupOpt::List(copt) => {
|
GroupOpt::List(copt) => {
|
||||||
let client = copt.to_client();
|
let client = copt.to_client();
|
||||||
let r = client.idm_group_list().unwrap();
|
match client.idm_group_list() {
|
||||||
for e in r {
|
Ok(r) => r.iter().for_each(|ent| println!("{}", ent)),
|
||||||
println!("{}", e);
|
Err(e) => {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GroupOpt::Create(gcopt) => {
|
GroupOpt::Create(gcopt) => {
|
||||||
let client = gcopt.copt.to_client();
|
let client = gcopt.copt.to_client();
|
||||||
client.idm_group_create(gcopt.name.as_str()).unwrap();
|
if let Err(e) = client.idm_group_create(gcopt.name.as_str()) {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
GroupOpt::Delete(gcopt) => {
|
GroupOpt::Delete(gcopt) => {
|
||||||
let client = gcopt.copt.to_client();
|
let client = gcopt.copt.to_client();
|
||||||
client.idm_group_delete(gcopt.name.as_str()).unwrap();
|
if let Err(e) = client.idm_group_delete(gcopt.name.as_str()) {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
GroupOpt::PurgeMembers(gcopt) => {
|
GroupOpt::PurgeMembers(gcopt) => {
|
||||||
let client = gcopt.copt.to_client();
|
let client = gcopt.copt.to_client();
|
||||||
client.idm_group_purge_members(gcopt.name.as_str()).unwrap();
|
if let Err(e) = client.idm_group_purge_members(gcopt.name.as_str()) {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
GroupOpt::ListMembers(gcopt) => {
|
GroupOpt::ListMembers(gcopt) => {
|
||||||
let client = gcopt.copt.to_client();
|
let client = gcopt.copt.to_client();
|
||||||
let members = client.idm_group_get_members(gcopt.name.as_str()).unwrap();
|
match client.idm_group_get_members(gcopt.name.as_str()) {
|
||||||
if let Some(groups) = members {
|
Ok(Some(groups)) => groups.iter().for_each(|m| println!("{:?}", m)),
|
||||||
for m in groups {
|
Ok(None) => {}
|
||||||
println!("{:?}", m);
|
Err(e) => {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,31 +109,33 @@ impl GroupOpt {
|
||||||
let client = gcopt.copt.to_client();
|
let client = gcopt.copt.to_client();
|
||||||
let new_members: Vec<&str> = gcopt.members.iter().map(|s| s.as_str()).collect();
|
let new_members: Vec<&str> = gcopt.members.iter().map(|s| s.as_str()).collect();
|
||||||
|
|
||||||
client
|
if let Err(e) = client.idm_group_add_members(gcopt.name.as_str(), &new_members) {
|
||||||
.idm_group_add_members(gcopt.name.as_str(), new_members)
|
eprintln!("Error -> {:?}", e);
|
||||||
.unwrap();
|
}
|
||||||
}
|
}
|
||||||
GroupOpt::SetMembers(gcopt) => {
|
GroupOpt::SetMembers(gcopt) => {
|
||||||
let client = gcopt.copt.to_client();
|
let client = gcopt.copt.to_client();
|
||||||
let new_members: Vec<&str> = gcopt.members.iter().map(|s| s.as_str()).collect();
|
let new_members: Vec<&str> = gcopt.members.iter().map(|s| s.as_str()).collect();
|
||||||
|
|
||||||
client
|
if let Err(e) = client.idm_group_set_members(gcopt.name.as_str(), &new_members) {
|
||||||
.idm_group_set_members(gcopt.name.as_str(), new_members)
|
eprintln!("Error -> {:?}", e);
|
||||||
.unwrap();
|
}
|
||||||
}
|
}
|
||||||
GroupOpt::Posix(gpopt) => match gpopt {
|
GroupOpt::Posix(gpopt) => match gpopt {
|
||||||
GroupPosix::Show(gcopt) => {
|
GroupPosix::Show(gcopt) => {
|
||||||
let client = gcopt.copt.to_client();
|
let client = gcopt.copt.to_client();
|
||||||
let token = client
|
match client.idm_group_unix_token_get(gcopt.name.as_str()) {
|
||||||
.idm_group_unix_token_get(gcopt.name.as_str())
|
Ok(token) => println!("{}", token),
|
||||||
.unwrap();
|
Err(e) => eprintln!("Error -> {:?}", e),
|
||||||
println!("{}", token);
|
}
|
||||||
}
|
}
|
||||||
GroupPosix::Set(gcopt) => {
|
GroupPosix::Set(gcopt) => {
|
||||||
let client = gcopt.copt.to_client();
|
let client = gcopt.copt.to_client();
|
||||||
client
|
if let Err(e) =
|
||||||
.idm_group_unix_extend(gcopt.name.as_str(), gcopt.gidnumber)
|
client.idm_group_unix_extend(gcopt.name.as_str(), gcopt.gidnumber)
|
||||||
.unwrap();
|
{
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
} // end match
|
} // end match
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
#![deny(warnings)]
|
||||||
|
#![warn(unused_extern_crates)]
|
||||||
|
#![deny(clippy::unwrap_used)]
|
||||||
|
#![deny(clippy::expect_used)]
|
||||||
|
#![deny(clippy::panic)]
|
||||||
|
#![deny(clippy::unreachable)]
|
||||||
|
#![deny(clippy::await_holding_lock)]
|
||||||
|
#![deny(clippy::needless_pass_by_value)]
|
||||||
|
#![deny(clippy::trivially_copy_pass_by_ref)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
@ -52,9 +62,17 @@ impl SelfOpt {
|
||||||
SelfOpt::SetPassword(copt) => {
|
SelfOpt::SetPassword(copt) => {
|
||||||
let client = copt.to_client();
|
let client = copt.to_client();
|
||||||
|
|
||||||
let password = rpassword::prompt_password_stderr("Enter new password: ").unwrap();
|
let password = match rpassword::prompt_password_stderr("Enter new password: ") {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
client.idm_account_set_password(password).unwrap();
|
if let Err(e) = client.idm_account_set_password(password) {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,14 +121,23 @@ impl ClientOpt {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn password_prompt(prompt: &str) -> Option<String> {
|
pub(crate) fn password_prompt(prompt: &str) -> Option<String> {
|
||||||
let password = rpassword::prompt_password_stderr(prompt).unwrap();
|
for _ in 0..3 {
|
||||||
|
let password = match rpassword::prompt_password_stderr(prompt) {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(_e) => return None,
|
||||||
|
};
|
||||||
|
|
||||||
let password_confirm =
|
let password_confirm =
|
||||||
rpassword::prompt_password_stderr("Retype the new password to confirm: ").unwrap();
|
match rpassword::prompt_password_stderr("Retype the new password to confirm: ") {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(_e) => return None,
|
||||||
|
};
|
||||||
|
|
||||||
if password == password_confirm {
|
if password == password_confirm {
|
||||||
Some(password)
|
return Some(password);
|
||||||
} else {
|
} else {
|
||||||
|
eprintln!("Passwords do not match");
|
||||||
|
}
|
||||||
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -11,14 +11,6 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
|
|
||||||
fn read_file<T: DeserializeOwned, P: AsRef<Path>>(path: P) -> Result<T, Box<dyn Error>> {
|
|
||||||
let f = File::open(path)?;
|
|
||||||
let r = BufReader::new(f);
|
|
||||||
|
|
||||||
let t: T = serde_json::from_reader(r)?;
|
|
||||||
Ok(t)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
#[derive(Debug, StructOpt)]
|
||||||
pub struct FilterOpt {
|
pub struct FilterOpt {
|
||||||
#[structopt()]
|
#[structopt()]
|
||||||
|
@ -30,7 +22,7 @@ pub struct FilterOpt {
|
||||||
#[derive(Debug, StructOpt)]
|
#[derive(Debug, StructOpt)]
|
||||||
pub struct CreateOpt {
|
pub struct CreateOpt {
|
||||||
#[structopt(parse(from_os_str))]
|
#[structopt(parse(from_os_str))]
|
||||||
file: Option<PathBuf>,
|
file: PathBuf,
|
||||||
#[structopt(flatten)]
|
#[structopt(flatten)]
|
||||||
commonopts: CommonOpt,
|
commonopts: CommonOpt,
|
||||||
}
|
}
|
||||||
|
@ -42,7 +34,7 @@ pub struct ModifyOpt {
|
||||||
#[structopt()]
|
#[structopt()]
|
||||||
filter: String,
|
filter: String,
|
||||||
#[structopt(parse(from_os_str))]
|
#[structopt(parse(from_os_str))]
|
||||||
file: Option<PathBuf>,
|
file: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, StructOpt)]
|
#[derive(Debug, StructOpt)]
|
||||||
|
@ -57,6 +49,14 @@ pub enum RawOpt {
|
||||||
Delete(FilterOpt),
|
Delete(FilterOpt),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_file<T: DeserializeOwned, P: AsRef<Path>>(path: P) -> Result<T, Box<dyn Error>> {
|
||||||
|
let f = File::open(path)?;
|
||||||
|
let r = BufReader::new(f);
|
||||||
|
|
||||||
|
let t: T = serde_json::from_reader(r)?;
|
||||||
|
Ok(t)
|
||||||
|
}
|
||||||
|
|
||||||
impl RawOpt {
|
impl RawOpt {
|
||||||
pub fn debug(&self) -> bool {
|
pub fn debug(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
|
@ -72,46 +72,75 @@ impl RawOpt {
|
||||||
RawOpt::Search(sopt) => {
|
RawOpt::Search(sopt) => {
|
||||||
let client = sopt.commonopts.to_client();
|
let client = sopt.commonopts.to_client();
|
||||||
|
|
||||||
let filter: Filter = serde_json::from_str(sopt.filter.as_str()).unwrap();
|
let filter: Filter = match serde_json::from_str(sopt.filter.as_str()) {
|
||||||
let rset = client.search(filter).unwrap();
|
Ok(f) => f,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
rset.iter().for_each(|e| {
|
match client.search(filter) {
|
||||||
println!("{}", e);
|
Ok(rset) => rset.iter().for_each(|e| println!("{}", e)),
|
||||||
});
|
Err(e) => {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
RawOpt::Create(copt) => {
|
RawOpt::Create(copt) => {
|
||||||
let client = copt.commonopts.to_client();
|
let client = copt.commonopts.to_client();
|
||||||
// Read the file?
|
// Read the file?
|
||||||
match &copt.file {
|
let r_entries: Vec<BTreeMap<String, Vec<String>>> = match read_file(&copt.file) {
|
||||||
Some(p) => {
|
Ok(r) => r,
|
||||||
let r_entries: Vec<BTreeMap<String, Vec<String>>> = read_file(p).unwrap();
|
Err(e) => {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let entries = r_entries.into_iter().map(|b| Entry { attrs: b }).collect();
|
let entries = r_entries.into_iter().map(|b| Entry { attrs: b }).collect();
|
||||||
client.create(entries).unwrap();
|
|
||||||
}
|
if let Err(e) = client.create(entries) {
|
||||||
None => {
|
eprintln!("Error -> {:?}", e);
|
||||||
println!("Must provide a file");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RawOpt::Modify(mopt) => {
|
RawOpt::Modify(mopt) => {
|
||||||
let client = mopt.commonopts.to_client();
|
let client = mopt.commonopts.to_client();
|
||||||
// Read the file?
|
// Read the file?
|
||||||
match &mopt.file {
|
let filter: Filter = match serde_json::from_str(mopt.filter.as_str()) {
|
||||||
Some(p) => {
|
Ok(f) => f,
|
||||||
let filter: Filter = serde_json::from_str(mopt.filter.as_str()).unwrap();
|
Err(e) => {
|
||||||
let r_list: Vec<Modify> = read_file(p).unwrap();
|
eprintln!("Error -> {:?}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let r_list: Vec<Modify> = match read_file(&mopt.file) {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let modlist = ModifyList::new_list(r_list);
|
let modlist = ModifyList::new_list(r_list);
|
||||||
client.modify(filter, modlist).unwrap();
|
if let Err(e) = client.modify(filter, modlist) {
|
||||||
}
|
eprintln!("Error -> {:?}", e);
|
||||||
None => {
|
|
||||||
println!("Must provide a file");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RawOpt::Delete(dopt) => {
|
RawOpt::Delete(dopt) => {
|
||||||
let client = dopt.commonopts.to_client();
|
let client = dopt.commonopts.to_client();
|
||||||
let filter: Filter = serde_json::from_str(dopt.filter.as_str()).unwrap();
|
let filter: Filter = match serde_json::from_str(dopt.filter.as_str()) {
|
||||||
client.delete(filter).unwrap();
|
Ok(f) => f,
|
||||||
|
Err(e) => {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(e) = client.delete(filter) {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,22 +27,28 @@ impl RecycleOpt {
|
||||||
match self {
|
match self {
|
||||||
RecycleOpt::List(copt) => {
|
RecycleOpt::List(copt) => {
|
||||||
let client = copt.to_client();
|
let client = copt.to_client();
|
||||||
let r = client.recycle_bin_list().unwrap();
|
match client.recycle_bin_list() {
|
||||||
for e in r {
|
Ok(r) => r.iter().for_each(|e| println!("{}", e)),
|
||||||
println!("{}", e);
|
Err(e) => {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RecycleOpt::Get(nopt) => {
|
RecycleOpt::Get(nopt) => {
|
||||||
let client = nopt.copt.to_client();
|
let client = nopt.copt.to_client();
|
||||||
let e = client.recycle_bin_get(nopt.name.as_str()).unwrap();
|
match client.recycle_bin_get(nopt.name.as_str()) {
|
||||||
match e {
|
Ok(Some(e)) => println!("{}", e),
|
||||||
Some(e) => println!("{}", e),
|
Ok(None) => println!("No matching entries"),
|
||||||
None => println!("No matching entries"),
|
Err(e) => {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RecycleOpt::Revive(nopt) => {
|
RecycleOpt::Revive(nopt) => {
|
||||||
let client = nopt.copt.to_client();
|
let client = nopt.copt.to_client();
|
||||||
client.recycle_bin_revive(nopt.name.as_str()).unwrap();
|
if let Err(e) = client.recycle_bin_revive(nopt.name.as_str()) {
|
||||||
|
eprintln!("Error -> {:?}", e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,13 @@
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
|
#![warn(unused_extern_crates)]
|
||||||
|
#![deny(clippy::unwrap_used)]
|
||||||
|
#![deny(clippy::expect_used)]
|
||||||
|
#![deny(clippy::panic)]
|
||||||
|
#![deny(clippy::unreachable)]
|
||||||
|
#![deny(clippy::await_holding_lock)]
|
||||||
|
#![deny(clippy::needless_pass_by_value)]
|
||||||
|
#![deny(clippy::trivially_copy_pass_by_ref)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate libnss;
|
extern crate libnss;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -1,5 +1,14 @@
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
extern crate libc;
|
#![warn(unused_extern_crates)]
|
||||||
|
#![deny(clippy::unwrap_used)]
|
||||||
|
#![deny(clippy::expect_used)]
|
||||||
|
#![deny(clippy::panic)]
|
||||||
|
#![deny(clippy::unreachable)]
|
||||||
|
#![deny(clippy::await_holding_lock)]
|
||||||
|
#![deny(clippy::needless_pass_by_value)]
|
||||||
|
#![deny(clippy::trivially_copy_pass_by_ref)]
|
||||||
|
|
||||||
|
// extern crate libc;
|
||||||
|
|
||||||
mod pam;
|
mod pam;
|
||||||
use crate::pam::constants::*;
|
use crate::pam::constants::*;
|
||||||
|
|
|
@ -271,8 +271,12 @@ impl CacheLayer {
|
||||||
ClientError::Http(
|
ClientError::Http(
|
||||||
StatusCode::UNAUTHORIZED,
|
StatusCode::UNAUTHORIZED,
|
||||||
Some(OperationError::NotAuthenticated),
|
Some(OperationError::NotAuthenticated),
|
||||||
|
opid,
|
||||||
) => {
|
) => {
|
||||||
error!("transport unauthenticated, moving to offline");
|
error!(
|
||||||
|
"transport unauthenticated, moving to offline - eventid {}",
|
||||||
|
opid
|
||||||
|
);
|
||||||
// Something went wrong, mark offline.
|
// Something went wrong, mark offline.
|
||||||
let time = SystemTime::now().add(Duration::from_secs(15));
|
let time = SystemTime::now().add(Duration::from_secs(15));
|
||||||
self.set_cachestate(CacheState::OfflineNextCheck(time))
|
self.set_cachestate(CacheState::OfflineNextCheck(time))
|
||||||
|
@ -282,14 +286,16 @@ impl CacheLayer {
|
||||||
ClientError::Http(
|
ClientError::Http(
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
Some(OperationError::NoMatchingEntries),
|
Some(OperationError::NoMatchingEntries),
|
||||||
|
opid,
|
||||||
)
|
)
|
||||||
| ClientError::Http(
|
| ClientError::Http(
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
Some(OperationError::InvalidAccountState(_)),
|
Some(OperationError::InvalidAccountState(_)),
|
||||||
|
opid,
|
||||||
) => {
|
) => {
|
||||||
// We wele able to contact the server but the entry has been removed, or
|
// We wele able to contact the server but the entry has been removed, or
|
||||||
// is not longer a valid posix account.
|
// is not longer a valid posix account.
|
||||||
debug!("entry has been removed or is no longer a valid posix account, clearing from cache ...");
|
debug!("entry has been removed or is no longer a valid posix account, clearing from cache ... - eventid {}", opid);
|
||||||
token
|
token
|
||||||
.map(|tok| self.delete_cache_usertoken(&tok.uuid))
|
.map(|tok| self.delete_cache_usertoken(&tok.uuid))
|
||||||
// Now an option<result<t, _>>
|
// Now an option<result<t, _>>
|
||||||
|
@ -335,8 +341,12 @@ impl CacheLayer {
|
||||||
ClientError::Http(
|
ClientError::Http(
|
||||||
StatusCode::UNAUTHORIZED,
|
StatusCode::UNAUTHORIZED,
|
||||||
Some(OperationError::NotAuthenticated),
|
Some(OperationError::NotAuthenticated),
|
||||||
|
opid,
|
||||||
) => {
|
) => {
|
||||||
error!("transport unauthenticated, moving to offline");
|
error!(
|
||||||
|
"transport unauthenticated, moving to offline - eventid {}",
|
||||||
|
opid
|
||||||
|
);
|
||||||
// Something went wrong, mark offline.
|
// Something went wrong, mark offline.
|
||||||
let time = SystemTime::now().add(Duration::from_secs(15));
|
let time = SystemTime::now().add(Duration::from_secs(15));
|
||||||
self.set_cachestate(CacheState::OfflineNextCheck(time))
|
self.set_cachestate(CacheState::OfflineNextCheck(time))
|
||||||
|
@ -346,12 +356,14 @@ impl CacheLayer {
|
||||||
ClientError::Http(
|
ClientError::Http(
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
Some(OperationError::NoMatchingEntries),
|
Some(OperationError::NoMatchingEntries),
|
||||||
|
opid,
|
||||||
)
|
)
|
||||||
| ClientError::Http(
|
| ClientError::Http(
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
Some(OperationError::InvalidAccountState(_)),
|
Some(OperationError::InvalidAccountState(_)),
|
||||||
|
opid,
|
||||||
) => {
|
) => {
|
||||||
debug!("entry has been removed or is no longer a valid posix group, clearing from cache ...");
|
debug!("entry has been removed or is no longer a valid posix group, clearing from cache ... - eventid {}", opid);
|
||||||
token
|
token
|
||||||
.map(|tok| self.delete_cache_grouptoken(&tok.uuid))
|
.map(|tok| self.delete_cache_grouptoken(&tok.uuid))
|
||||||
// Now an option<result<t, _>>
|
// Now an option<result<t, _>>
|
||||||
|
@ -620,8 +632,12 @@ impl CacheLayer {
|
||||||
ClientError::Http(
|
ClientError::Http(
|
||||||
StatusCode::UNAUTHORIZED,
|
StatusCode::UNAUTHORIZED,
|
||||||
Some(OperationError::NotAuthenticated),
|
Some(OperationError::NotAuthenticated),
|
||||||
|
opid,
|
||||||
) => {
|
) => {
|
||||||
error!("transport unauthenticated, moving to offline");
|
error!(
|
||||||
|
"transport unauthenticated, moving to offline - eventid {}",
|
||||||
|
opid
|
||||||
|
);
|
||||||
// Something went wrong, mark offline.
|
// Something went wrong, mark offline.
|
||||||
let time = SystemTime::now().add(Duration::from_secs(15));
|
let time = SystemTime::now().add(Duration::from_secs(15));
|
||||||
self.set_cachestate(CacheState::OfflineNextCheck(time))
|
self.set_cachestate(CacheState::OfflineNextCheck(time))
|
||||||
|
@ -634,12 +650,17 @@ impl CacheLayer {
|
||||||
ClientError::Http(
|
ClientError::Http(
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
Some(OperationError::NoMatchingEntries),
|
Some(OperationError::NoMatchingEntries),
|
||||||
|
opid,
|
||||||
)
|
)
|
||||||
| ClientError::Http(
|
| ClientError::Http(
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
Some(OperationError::InvalidAccountState(_)),
|
Some(OperationError::InvalidAccountState(_)),
|
||||||
|
opid,
|
||||||
) => {
|
) => {
|
||||||
error!("unknown account or is not a valid posix account");
|
error!(
|
||||||
|
"unknown account or is not a valid posix account - eventid {}",
|
||||||
|
opid
|
||||||
|
);
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
er => {
|
er => {
|
||||||
|
|
|
@ -1,4 +1,13 @@
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
|
#![warn(unused_extern_crates)]
|
||||||
|
#![deny(clippy::unwrap_used)]
|
||||||
|
#![deny(clippy::expect_used)]
|
||||||
|
#![deny(clippy::panic)]
|
||||||
|
#![deny(clippy::unreachable)]
|
||||||
|
#![deny(clippy::await_holding_lock)]
|
||||||
|
#![deny(clippy::needless_pass_by_value)]
|
||||||
|
#![deny(clippy::trivially_copy_pass_by_ref)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::convert::TryFrom;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use crate::cache::Id;
|
use crate::cache::Id;
|
||||||
use std::sync::{Mutex, MutexGuard};
|
use tokio::sync::{Mutex, MutexGuard};
|
||||||
|
|
||||||
use kanidm::be::dbvalue::DbPasswordV1;
|
use kanidm::be::dbvalue::DbPasswordV1;
|
||||||
use kanidm::credential::Password;
|
use kanidm::credential::Password;
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
#![warn(unused_extern_crates)]
|
#![warn(unused_extern_crates)]
|
||||||
|
#![deny(clippy::unwrap_used)]
|
||||||
|
#![deny(clippy::expect_used)]
|
||||||
|
#![deny(clippy::panic)]
|
||||||
|
#![deny(clippy::unreachable)]
|
||||||
|
#![deny(clippy::await_holding_lock)]
|
||||||
|
#![deny(clippy::needless_pass_by_value)]
|
||||||
|
#![deny(clippy::trivially_copy_pass_by_ref)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
|
|
@ -101,7 +101,7 @@ fn test_fixture(rsclient: &KanidmClient) -> () {
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
// Not recommended in production!
|
// Not recommended in production!
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_add_members("idm_admins", vec!["admin"])
|
.idm_group_add_members("idm_admins", &["admin"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Create a new account
|
// Create a new account
|
||||||
|
@ -126,7 +126,7 @@ fn test_fixture(rsclient: &KanidmClient) -> () {
|
||||||
// Setup a group
|
// Setup a group
|
||||||
rsclient.idm_group_create("testgroup1").unwrap();
|
rsclient.idm_group_create("testgroup1").unwrap();
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_add_members("testgroup1", vec!["testaccount1"])
|
.idm_group_add_members("testgroup1", &["testaccount1"])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
rsclient
|
rsclient
|
||||||
.idm_group_unix_extend("testgroup1", Some(20001))
|
.idm_group_unix_extend("testgroup1", Some(20001))
|
||||||
|
|
|
@ -63,12 +63,12 @@ macro_rules! try_from_entry {
|
||||||
let uuid = $value.get_uuid().clone();
|
let uuid = $value.get_uuid().clone();
|
||||||
|
|
||||||
Ok(Account {
|
Ok(Account {
|
||||||
uuid: uuid,
|
uuid,
|
||||||
name: name,
|
name,
|
||||||
displayname: displayname,
|
displayname,
|
||||||
groups: groups,
|
groups,
|
||||||
primary: primary,
|
primary,
|
||||||
spn: spn,
|
spn,
|
||||||
})
|
})
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
#![warn(unused_extern_crates)]
|
#![warn(unused_extern_crates)]
|
||||||
|
#![deny(clippy::unwrap_used)]
|
||||||
|
#![deny(clippy::expect_used)]
|
||||||
|
#![deny(clippy::panic)]
|
||||||
|
#![deny(clippy::unreachable)]
|
||||||
|
#![deny(clippy::await_holding_lock)]
|
||||||
|
#![deny(clippy::needless_pass_by_value)]
|
||||||
|
#![deny(clippy::trivially_copy_pass_by_ref)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate log;
|
extern crate log;
|
||||||
|
|
Loading…
Reference in a new issue