From 217e3455a250d3f4ea229d69ee1b8280a68eca5d Mon Sep 17 00:00:00 2001 From: William Brown Date: Sat, 1 Aug 2020 20:31:05 +1000 Subject: [PATCH] Cleanup and improve client error handling --- kanidm_client/src/asynchronous.rs | 141 ++++++++++++------ kanidm_client/src/lib.rs | 126 +++++++++------- kanidm_client/tests/default_entries.rs | 16 +-- kanidm_client/tests/proto_v1_test.rs | 20 +-- kanidm_tools/src/cli/account.rs | 167 ++++++++++++---------- kanidm_tools/src/cli/common.rs | 41 ++++-- kanidm_tools/src/cli/group.rs | 57 +++++--- kanidm_tools/src/cli/lib.rs | 45 ++++-- kanidm_tools/src/cli/raw.rs | 95 +++++++----- kanidm_tools/src/cli/recycle.rs | 22 +-- kanidm_unix_int/nss_kanidm/src/lib.rs | 9 ++ kanidm_unix_int/pam_kanidm/src/lib.rs | 11 +- kanidm_unix_int/src/cache.rs | 33 ++++- kanidm_unix_int/src/daemon.rs | 9 ++ kanidm_unix_int/src/db.rs | 2 +- kanidm_unix_int/src/lib.rs | 7 + kanidm_unix_int/tests/cache_layer_test.rs | 4 +- kanidmd/src/lib/idm/account.rs | 12 +- kanidmd/src/lib/lib.rs | 7 + 19 files changed, 532 insertions(+), 292 deletions(-) diff --git a/kanidm_client/src/asynchronous.rs b/kanidm_client/src/asynchronous.rs index b3d1d4fa2..d165c4c94 100644 --- a/kanidm_client/src/asynchronous.rs +++ b/kanidm_client/src/asynchronous.rs @@ -23,7 +23,7 @@ impl KanidmAsyncClient { // format doesn't work in async ?! // 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 .client @@ -34,21 +34,28 @@ impl KanidmAsyncClient { .await .map_err(ClientError::Transport)?; - let opid = response.headers().get(KOPID); - debug!( - "opid -> {:?}", - opid.expect("Missing opid? Refusing to proceed ...") - ); + 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() { 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 - let r: T = response.json().await.unwrap(); - - Ok(r) + response + .json() + .await + .map_err(|e| ClientError::JSONDecode(e, opid)) } async fn perform_put_request( @@ -61,7 +68,7 @@ impl KanidmAsyncClient { // format doesn't work in async ?! // 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 .client @@ -72,21 +79,29 @@ impl KanidmAsyncClient { .await .map_err(ClientError::Transport)?; - let opid = response.headers().get(KOPID); - debug!( - "opid -> {:?}", - opid.expect("Missing opid? Refusing to proceed ...") - ); + 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() { 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 - let r: T = response.json().await.unwrap(); - - Ok(r) + response + .json() + .await + .map_err(|e| ClientError::JSONDecode(e, opid)) } async fn perform_get_request(&self, dest: &str) -> Result { @@ -100,21 +115,29 @@ impl KanidmAsyncClient { .await .map_err(ClientError::Transport)?; - let opid = response.headers().get(KOPID); - debug!( - "opid -> {:?}", - opid.expect("Missing opid? Refusing to proceed ...") - ); + 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() { 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 - let r: T = response.json().await.unwrap(); - - Ok(r) + response + .json() + .await + .map_err(|e| ClientError::JSONDecode(e, opid)) } async fn perform_delete_request(&self, dest: &str) -> Result { @@ -126,20 +149,28 @@ impl KanidmAsyncClient { .await .map_err(ClientError::Transport)?; - let opid = response.headers().get(KOPID); - debug!( - "opid -> {:?}", - opid.expect("Missing opid? Refusing to proceed ...") - ); + 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() { 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(); - - Ok(r) + response + .json() + .await + .map_err(|e| ClientError::JSONDecode(e, opid)) } pub async fn auth_step_init(&self, ident: &str) -> Result { @@ -205,17 +236,37 @@ impl KanidmAsyncClient { let whoami_dest = [self.addr.as_str(), "/v1/self"].concat(); // format!("{}/v1/self", self.addr); 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() { // Continue to process. reqwest::StatusCode::OK => {} 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 = - serde_json::from_str(response.text().await.unwrap().as_str()).unwrap(); + let r: WhoamiResponse = response + .json() + .await + .map_err(|e| ClientError::JSONDecode(e, opid))?; Ok(Some((r.youare, r.uat))) } diff --git a/kanidm_client/src/lib.rs b/kanidm_client/src/lib.rs index 5afddf356..99e4a8e80 100644 --- a/kanidm_client/src/lib.rs +++ b/kanidm_client/src/lib.rs @@ -1,5 +1,12 @@ #![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] extern crate log; @@ -8,6 +15,7 @@ use reqwest::header::CONTENT_TYPE; use serde::de::DeserializeOwned; use serde::Serialize; use serde_derive::Deserialize; +use serde_json::error::Error as SerdeJsonError; use std::collections::BTreeMap; use std::fs::{metadata, File, Metadata}; use std::io::Read; @@ -35,12 +43,13 @@ pub const KOPID: &str = "X-KANIDM-OPID"; #[derive(Debug)] pub enum ClientError { Unauthorized, - Http(reqwest::StatusCode, Option), + Http(reqwest::StatusCode, Option, String), Transport(reqwest::Error), AuthenticationFailed, - JsonParse, EmptyResponse, TOTPVerifyFailed(Uuid, TOTPSecret), + JSONDecode(reqwest::Error, String), + JSONEncode(SerdeJsonError), } #[derive(Debug, Deserialize)] @@ -341,7 +350,7 @@ impl KanidmClient { ) -> Result { 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 .client @@ -351,21 +360,21 @@ impl KanidmClient { .send() .map_err(ClientError::Transport)?; - let opid = response.headers().get(KOPID); - debug!( - "opid -> {:?}", - opid.expect("Missing opid? Refusing to proceed ...") - ); + 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() { 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 - let r: T = response.json().unwrap(); - - Ok(r) + response + .json() + .map_err(|e| ClientError::JSONDecode(e, opid)) } fn perform_put_request( @@ -375,7 +384,7 @@ impl KanidmClient { ) -> Result { 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 .client @@ -385,21 +394,21 @@ impl KanidmClient { .send() .map_err(ClientError::Transport)?; - let opid = response.headers().get(KOPID); - debug!( - "opid -> {:?}", - opid.expect("Missing opid? Refusing to proceed ...") - ); + 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() { 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 - let r: T = response.json().unwrap(); - - Ok(r) + response + .json() + .map_err(|e| ClientError::JSONDecode(e, opid)) } fn perform_get_request(&self, dest: &str) -> Result { @@ -410,21 +419,21 @@ impl KanidmClient { .send() .map_err(ClientError::Transport)?; - let opid = response.headers().get(KOPID); - debug!( - "opid -> {:?}", - opid.expect("Missing opid? Refusing to proceed ...") - ); + 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() { 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 - let r: T = response.json().unwrap(); - - Ok(r) + response + .json() + .map_err(|e| ClientError::JSONDecode(e, opid)) } fn perform_delete_request(&self, dest: &str) -> Result { @@ -435,36 +444,50 @@ impl KanidmClient { .send() .map_err(ClientError::Transport)?; - let opid = response.headers().get(KOPID); - debug!( - "opid -> {:?}", - opid.expect("Missing opid? Refusing to proceed ...") - ); + 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() { 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(); - - Ok(r) + response + .json() + .map_err(|e| ClientError::JSONDecode(e, opid)) } // whoami // Can't use generic get due to possible un-auth case. pub fn whoami(&self) -> Result, ClientError> { 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() { // Continue to process. reqwest::StatusCode::OK => {} 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))) } @@ -608,12 +631,12 @@ impl KanidmClient { 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 { + pub fn idm_group_set_members(&self, id: &str, members: &[&str]) -> Result { let m: Vec<_> = members.iter().map(|v| (*v).to_string()).collect(); 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 { + pub fn idm_group_add_members(&self, id: &str, members: &[&str]) -> Result { let m: Vec<_> = members.iter().map(|v| (*v).to_string()).collect(); 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_ssid(&self, id: &str) -> Result { self.perform_get_request(format!("/v1/domain/{}/_attr/domain_ssid", id).as_str()) - .and_then(|mut r: Vec| Ok(r.pop().unwrap())) + .and_then(|mut r: Vec| + // Get the first result + r.pop() + .ok_or( + ClientError::EmptyResponse + )) } // pub fn idm_domain_put_attr diff --git a/kanidm_client/tests/default_entries.rs b/kanidm_client/tests/default_entries.rs index 50de43be2..5b9131e2f 100644 --- a/kanidm_client/tests/default_entries.rs +++ b/kanidm_client/tests/default_entries.rs @@ -63,9 +63,7 @@ fn create_user(rsclient: &KanidmClient, id: &str, group_name: &str) -> () { None => rsclient.idm_group_create(&group_name).unwrap(), }; - rsclient - .idm_group_add_members(&group_name, vec![id]) - .unwrap(); + rsclient.idm_group_add_members(&group_name, &[id]).unwrap(); } fn is_attr_writable(rsclient: &KanidmClient, id: &str, attr: &str) -> Option { @@ -115,7 +113,7 @@ fn is_attr_writable(rsclient: &KanidmClient, id: &str, attr: &str) -> Option () { 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(); rsclient - .idm_group_add_members("idm_people_extend_priv", vec!["admin"]) + .idm_group_add_members("idm_people_extend_priv", &["admin"]) .unwrap(); rsclient @@ -215,7 +213,7 @@ fn test_modify_group(rsclient: &KanidmClient, group_names: &[&str], is_modificab ["description", "name"].iter().for_each(|attr| { 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_add_members("test_group", vec!["test"]) + .idm_group_add_members("test_group", &["test"]) .unwrap(); assert!(is_attr_writable(&rsclient, "test_group", "description").unwrap()); }); @@ -588,7 +586,7 @@ fn test_default_entries_rbac_anonymous_entry() { .unwrap(); create_user_with_all_attrs(&mut rsclient, "test", Some("test_group")); rsclient - .idm_group_add_members("test_group", vec!["anonymous"]) + .idm_group_add_members("test_group", &["anonymous"]) .unwrap(); add_all_attrs(&mut rsclient, "anonymous", "test_group"); diff --git a/kanidm_client/tests/proto_v1_test.rs b/kanidm_client/tests/proto_v1_test.rs index 04c401526..f5f000650 100644 --- a/kanidm_client/tests/proto_v1_test.rs +++ b/kanidm_client/tests/proto_v1_test.rs @@ -251,14 +251,14 @@ fn test_server_rest_group_lifecycle() { // Add a member. rsclient - .idm_group_add_members("demo_group", vec!["admin"]) + .idm_group_add_members("demo_group", &["admin"]) .unwrap(); let members = rsclient.idm_group_get_members("demo_group").unwrap(); assert!(members == Some(vec!["admin@example.com".to_string()])); // Set the list of members rsclient - .idm_group_set_members("demo_group", vec!["admin", "demo_group"]) + .idm_group_set_members("demo_group", &["admin", "demo_group"]) .unwrap(); let members = rsclient.idm_group_get_members("demo_group").unwrap(); 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 make them a people admin. NOT recommended in production! rsclient - .idm_group_add_members("idm_account_write_priv", vec!["admin"]) + .idm_group_add_members("idm_account_write_priv", &["admin"]) .unwrap(); // Create a new account @@ -499,7 +499,7 @@ fn test_server_rest_posix_lifecycle() { assert!(res.is_ok()); // Not recommended in production! rsclient - .idm_group_add_members("idm_admins", vec!["admin"]) + .idm_group_add_members("idm_admins", &["admin"]) .unwrap(); // Create a new account @@ -517,7 +517,7 @@ fn test_server_rest_posix_lifecycle() { // Extend the group with posix attrs rsclient.idm_group_create("posix_group").unwrap(); rsclient - .idm_group_add_members("posix_group", vec!["posix_account"]) + .idm_group_add_members("posix_group", &["posix_account"]) .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! rsclient - .idm_group_add_members("idm_admins", vec!["admin"]) + .idm_group_add_members("idm_admins", &["admin"]) .unwrap(); // Setup a unix user @@ -634,7 +634,7 @@ fn test_server_rest_recycle_lifecycle() { // Not recommended in production! rsclient - .idm_group_add_members("idm_admins", vec!["admin"]) + .idm_group_add_members("idm_admins", &["admin"]) .unwrap(); // 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 make them a password import admin. NOT recommended in production! 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(); rsclient - .idm_group_add_members("idm_people_extend_priv", vec!["admin"]) + .idm_group_add_members("idm_people_extend_priv", &["admin"]) .unwrap(); // Create a new account @@ -718,7 +718,7 @@ fn test_server_rest_totp_auth_lifecycle() { // Not recommended in production! rsclient - .idm_group_add_members("idm_admins", vec!["admin"]) + .idm_group_add_members("idm_admins", &["admin"]) .unwrap(); // Create a new account diff --git a/kanidm_tools/src/cli/account.rs b/kanidm_tools/src/cli/account.rs index 05d9cbb14..326cc1bdd 100644 --- a/kanidm_tools/src/cli/account.rs +++ b/kanidm_tools/src/cli/account.rs @@ -171,70 +171,82 @@ impl AccountOpt { } }; - client - .idm_account_primary_credential_set_password( - acsopt.aopts.account_id.as_str(), - password.as_str(), - ) - .unwrap(); + if let Err(e) = client.idm_account_primary_credential_set_password( + acsopt.aopts.account_id.as_str(), + password.as_str(), + ) { + eprintln!("Error -> {:?}", e); + } } AccountCredential::GeneratePassword(acsopt) => { let client = acsopt.copt.to_client(); - let npw = client - .idm_account_primary_credential_set_generated( - acsopt.aopts.account_id.as_str(), - ) - .unwrap(); - println!( - "Generated password for {}: {}", - acsopt.aopts.account_id, npw - ); + match client.idm_account_primary_credential_set_generated( + acsopt.aopts.account_id.as_str(), + ) { + Ok(npw) => { + println!( + "Generated password for {}: {}", + acsopt.aopts.account_id, npw + ); + } + Err(e) => { + eprintln!("Error -> {:?}", e); + } + } } }, // end AccountOpt::Credential AccountOpt::Radius(aropt) => match aropt { AccountRadius::Show(aopt) => { let client = aopt.copt.to_client(); - let rcred = client - .idm_account_radius_credential_get(aopt.aopts.account_id.as_str()) - .unwrap(); + let rcred = + client.idm_account_radius_credential_get(aopt.aopts.account_id.as_str()); match rcred { - Some(s) => println!("Radius secret: {}", s), - None => println!("NO Radius secret"), + Ok(Some(s)) => println!("Radius secret: {}", s), + Ok(None) => println!("NO Radius secret"), + Err(e) => { + eprintln!("Error -> {:?}", e); + } } } AccountRadius::Generate(aopt) => { let client = aopt.copt.to_client(); - client + if let Err(e) = client .idm_account_radius_credential_regenerate(aopt.aopts.account_id.as_str()) - .unwrap(); + { + eprintln!("Error -> {:?}", e); + } } AccountRadius::Delete(aopt) => { let client = aopt.copt.to_client(); - client - .idm_account_radius_credential_delete(aopt.aopts.account_id.as_str()) - .unwrap(); + if let Err(e) = + client.idm_account_radius_credential_delete(aopt.aopts.account_id.as_str()) + { + eprintln!("Error -> {:?}", e); + } } }, // end AccountOpt::Radius AccountOpt::Posix(apopt) => match apopt { AccountPosix::Show(aopt) => { let client = aopt.copt.to_client(); - let token = client - .idm_account_unix_token_get(aopt.aopts.account_id.as_str()) - .unwrap(); - println!("{}", token); + match client.idm_account_unix_token_get(aopt.aopts.account_id.as_str()) { + Ok(token) => println!("{}", token), + Err(e) => { + eprintln!("Error -> {:?}", e); + } + } } AccountPosix::Set(aopt) => { let client = aopt.copt.to_client(); - client - .idm_account_unix_extend( - aopt.aopts.account_id.as_str(), - aopt.gidnumber, - aopt.shell.as_deref(), - ) - .unwrap(); + if let Err(e) = client.idm_account_unix_extend( + aopt.aopts.account_id.as_str(), + aopt.gidnumber, + aopt.shell.as_deref(), + ) { + eprintln!("Error -> {:?}", e); + } } AccountPosix::SetPassword(aopt) => { let client = aopt.copt.to_client(); @@ -246,77 +258,74 @@ impl AccountOpt { } }; - client - .idm_account_unix_cred_put( - aopt.aopts.account_id.as_str(), - password.as_str(), - ) - .unwrap(); + if let Err(e) = client.idm_account_unix_cred_put( + aopt.aopts.account_id.as_str(), + password.as_str(), + ) { + eprintln!("Error -> {:?}", e); + } } }, // end AccountOpt::Posix AccountOpt::Ssh(asopt) => match asopt { AccountSsh::List(aopt) => { let client = aopt.copt.to_client(); - let pkeys = client - .idm_account_get_ssh_pubkeys(aopt.aopts.account_id.as_str()) - .unwrap(); - - for pkey in pkeys { - println!("{}", pkey) + match client.idm_account_get_ssh_pubkeys(aopt.aopts.account_id.as_str()) { + Ok(pkeys) => pkeys.iter().for_each(|pkey| println!("{}", pkey)), + Err(e) => { + eprintln!("Error -> {:?}", e); + } } } AccountSsh::Add(aopt) => { let client = aopt.copt.to_client(); - client - .idm_account_post_ssh_pubkey( - aopt.aopts.account_id.as_str(), - aopt.tag.as_str(), - aopt.pubkey.as_str(), - ) - .unwrap(); + if let Err(e) = client.idm_account_post_ssh_pubkey( + aopt.aopts.account_id.as_str(), + aopt.tag.as_str(), + aopt.pubkey.as_str(), + ) { + eprintln!("Error -> {:?}", e); + } } AccountSsh::Delete(aopt) => { let client = aopt.copt.to_client(); - client - .idm_account_delete_ssh_pubkey( - aopt.aopts.account_id.as_str(), - aopt.tag.as_str(), - ) - .unwrap(); + if let Err(e) = client.idm_account_delete_ssh_pubkey( + aopt.aopts.account_id.as_str(), + aopt.tag.as_str(), + ) { + eprintln!("Error -> {:?}", e); + } } }, // end AccountOpt::Ssh AccountOpt::List(copt) => { let client = copt.to_client(); - let r = client.idm_account_list().unwrap(); - for e in r { - println!("{}", e); + match client.idm_account_list() { + Ok(r) => r.iter().for_each(|ent| println!("{}", ent)), + Err(e) => eprintln!("Error -> {:?}", e), } } AccountOpt::Get(aopt) => { let client = aopt.copt.to_client(); - let e = client - .idm_account_get(aopt.aopts.account_id.as_str()) - .unwrap(); - match e { - Some(e) => println!("{}", e), - None => println!("No matching entries"), + match client.idm_account_get(aopt.aopts.account_id.as_str()) { + Ok(Some(e)) => println!("{}", e), + Ok(None) => println!("No matching entries"), + Err(e) => eprintln!("Error -> {:?}", e), } } AccountOpt::Delete(aopt) => { let client = aopt.copt.to_client(); - client - .idm_account_delete(aopt.aopts.account_id.as_str()) - .unwrap(); + if let Err(e) = client.idm_account_delete(aopt.aopts.account_id.as_str()) { + eprintln!("Error -> {:?}", e) + } } AccountOpt::Create(acopt) => { let client = acopt.copt.to_client(); - client - .idm_account_create( - acopt.aopts.account_id.as_str(), - acopt.display_name.as_str(), - ) - .unwrap(); + if let Err(e) = client.idm_account_create( + acopt.aopts.account_id.as_str(), + acopt.display_name.as_str(), + ) { + eprintln!("Error -> {:?}", e) + } } } } diff --git a/kanidm_tools/src/cli/common.rs b/kanidm_tools/src/cli/common.rs index 57509cdc7..1bbc5bb11 100644 --- a/kanidm_tools/src/cli/common.rs +++ b/kanidm_tools/src/cli/common.rs @@ -27,35 +27,54 @@ impl CommonOpt { let config_path: String = shellexpand::tilde("~/.config/kanidm").into_owned(); 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") .and_then(|cb| { debug!("Attempting to use 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 { Some(a) => client_builder.address(a.to_string()), 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 { - Some(p) => client_builder - .add_root_certificate_filepath(p) - .expect("Failed to access CA file"), + Some(p) => match client_builder.add_root_certificate_filepath(p) { + Ok(cb) => cb, + Err(e) => { + error!("Failed to add ca certificate -- {:?}", e); + std::process::exit(1); + } + }, None => client_builder, }; - let client = client_builder - .build() - .expect("Failed to build client instance"); + let client = match client_builder.build() { + Ok(c) => c, + Err(e) => { + error!("Failed to build client instance -- {:?}", e); + std::process::exit(1); + } + }; let r = if self.username == "anonymous" { client.auth_anonymous() } 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()) }; diff --git a/kanidm_tools/src/cli/group.rs b/kanidm_tools/src/cli/group.rs index 2cdc4ef43..150e6e99c 100644 --- a/kanidm_tools/src/cli/group.rs +++ b/kanidm_tools/src/cli/group.rs @@ -70,29 +70,38 @@ impl GroupOpt { match self { GroupOpt::List(copt) => { let client = copt.to_client(); - let r = client.idm_group_list().unwrap(); - for e in r { - println!("{}", e); + match client.idm_group_list() { + Ok(r) => r.iter().for_each(|ent| println!("{}", ent)), + Err(e) => { + eprintln!("Error -> {:?}", e); + } } } GroupOpt::Create(gcopt) => { 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) => { 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) => { 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) => { let client = gcopt.copt.to_client(); - let members = client.idm_group_get_members(gcopt.name.as_str()).unwrap(); - if let Some(groups) = members { - for m in groups { - println!("{:?}", m); + match client.idm_group_get_members(gcopt.name.as_str()) { + Ok(Some(groups)) => groups.iter().for_each(|m| println!("{:?}", m)), + Ok(None) => {} + Err(e) => { + eprintln!("Error -> {:?}", e); } } } @@ -100,31 +109,33 @@ impl GroupOpt { let client = gcopt.copt.to_client(); let new_members: Vec<&str> = gcopt.members.iter().map(|s| s.as_str()).collect(); - client - .idm_group_add_members(gcopt.name.as_str(), new_members) - .unwrap(); + if let Err(e) = client.idm_group_add_members(gcopt.name.as_str(), &new_members) { + eprintln!("Error -> {:?}", e); + } } GroupOpt::SetMembers(gcopt) => { let client = gcopt.copt.to_client(); let new_members: Vec<&str> = gcopt.members.iter().map(|s| s.as_str()).collect(); - client - .idm_group_set_members(gcopt.name.as_str(), new_members) - .unwrap(); + if let Err(e) = client.idm_group_set_members(gcopt.name.as_str(), &new_members) { + eprintln!("Error -> {:?}", e); + } } GroupOpt::Posix(gpopt) => match gpopt { GroupPosix::Show(gcopt) => { let client = gcopt.copt.to_client(); - let token = client - .idm_group_unix_token_get(gcopt.name.as_str()) - .unwrap(); - println!("{}", token); + match client.idm_group_unix_token_get(gcopt.name.as_str()) { + Ok(token) => println!("{}", token), + Err(e) => eprintln!("Error -> {:?}", e), + } } GroupPosix::Set(gcopt) => { let client = gcopt.copt.to_client(); - client - .idm_group_unix_extend(gcopt.name.as_str(), gcopt.gidnumber) - .unwrap(); + if let Err(e) = + client.idm_group_unix_extend(gcopt.name.as_str(), gcopt.gidnumber) + { + eprintln!("Error -> {:?}", e); + } } }, } // end match diff --git a/kanidm_tools/src/cli/lib.rs b/kanidm_tools/src/cli/lib.rs index b7c5ba0ba..997282264 100644 --- a/kanidm_tools/src/cli/lib.rs +++ b/kanidm_tools/src/cli/lib.rs @@ -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] extern crate log; use structopt::StructOpt; @@ -52,9 +62,17 @@ impl SelfOpt { SelfOpt::SetPassword(copt) => { 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 { - 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 = - rpassword::prompt_password_stderr("Retype the new password to confirm: ").unwrap(); + let password_confirm = + match rpassword::prompt_password_stderr("Retype the new password to confirm: ") { + Ok(p) => p, + Err(_e) => return None, + }; - if password == password_confirm { - Some(password) - } else { - None + if password == password_confirm { + return Some(password); + } else { + eprintln!("Passwords do not match"); + } } + None } diff --git a/kanidm_tools/src/cli/raw.rs b/kanidm_tools/src/cli/raw.rs index ea40c7cbe..ad9299d1e 100644 --- a/kanidm_tools/src/cli/raw.rs +++ b/kanidm_tools/src/cli/raw.rs @@ -11,14 +11,6 @@ use std::path::PathBuf; use serde::de::DeserializeOwned; -fn read_file>(path: P) -> Result> { - let f = File::open(path)?; - let r = BufReader::new(f); - - let t: T = serde_json::from_reader(r)?; - Ok(t) -} - #[derive(Debug, StructOpt)] pub struct FilterOpt { #[structopt()] @@ -30,7 +22,7 @@ pub struct FilterOpt { #[derive(Debug, StructOpt)] pub struct CreateOpt { #[structopt(parse(from_os_str))] - file: Option, + file: PathBuf, #[structopt(flatten)] commonopts: CommonOpt, } @@ -42,7 +34,7 @@ pub struct ModifyOpt { #[structopt()] filter: String, #[structopt(parse(from_os_str))] - file: Option, + file: PathBuf, } #[derive(Debug, StructOpt)] @@ -57,6 +49,14 @@ pub enum RawOpt { Delete(FilterOpt), } +fn read_file>(path: P) -> Result> { + let f = File::open(path)?; + let r = BufReader::new(f); + + let t: T = serde_json::from_reader(r)?; + Ok(t) +} + impl RawOpt { pub fn debug(&self) -> bool { match self { @@ -72,46 +72,75 @@ impl RawOpt { RawOpt::Search(sopt) => { let client = sopt.commonopts.to_client(); - let filter: Filter = serde_json::from_str(sopt.filter.as_str()).unwrap(); - let rset = client.search(filter).unwrap(); + let filter: Filter = match serde_json::from_str(sopt.filter.as_str()) { + Ok(f) => f, + Err(e) => { + eprintln!("Error -> {:?}", e); + return; + } + }; - rset.iter().for_each(|e| { - println!("{}", e); - }); + match client.search(filter) { + Ok(rset) => rset.iter().for_each(|e| println!("{}", e)), + Err(e) => { + eprintln!("Error -> {:?}", e); + } + } } RawOpt::Create(copt) => { let client = copt.commonopts.to_client(); // Read the file? - match &copt.file { - Some(p) => { - let r_entries: Vec>> = read_file(p).unwrap(); - let entries = r_entries.into_iter().map(|b| Entry { attrs: b }).collect(); - client.create(entries).unwrap(); - } - None => { - println!("Must provide a file"); + let r_entries: Vec>> = match read_file(&copt.file) { + Ok(r) => r, + Err(e) => { + eprintln!("Error -> {:?}", e); + return; } + }; + + let entries = r_entries.into_iter().map(|b| Entry { attrs: b }).collect(); + + if let Err(e) = client.create(entries) { + eprintln!("Error -> {:?}", e); } } RawOpt::Modify(mopt) => { let client = mopt.commonopts.to_client(); // Read the file? - match &mopt.file { - Some(p) => { - let filter: Filter = serde_json::from_str(mopt.filter.as_str()).unwrap(); - let r_list: Vec = read_file(p).unwrap(); - let modlist = ModifyList::new_list(r_list); - client.modify(filter, modlist).unwrap(); + let filter: Filter = match serde_json::from_str(mopt.filter.as_str()) { + Ok(f) => f, + Err(e) => { + eprintln!("Error -> {:?}", e); + return; } - None => { - println!("Must provide a file"); + }; + + let r_list: Vec = match read_file(&mopt.file) { + Ok(r) => r, + Err(e) => { + eprintln!("Error -> {:?}", e); + return; } + }; + + let modlist = ModifyList::new_list(r_list); + if let Err(e) = client.modify(filter, modlist) { + eprintln!("Error -> {:?}", e); } } RawOpt::Delete(dopt) => { let client = dopt.commonopts.to_client(); - let filter: Filter = serde_json::from_str(dopt.filter.as_str()).unwrap(); - client.delete(filter).unwrap(); + let filter: Filter = match serde_json::from_str(dopt.filter.as_str()) { + Ok(f) => f, + Err(e) => { + eprintln!("Error -> {:?}", e); + return; + } + }; + + if let Err(e) = client.delete(filter) { + eprintln!("Error -> {:?}", e); + } } } } diff --git a/kanidm_tools/src/cli/recycle.rs b/kanidm_tools/src/cli/recycle.rs index a9afd0c1b..3ed63081c 100644 --- a/kanidm_tools/src/cli/recycle.rs +++ b/kanidm_tools/src/cli/recycle.rs @@ -27,22 +27,28 @@ impl RecycleOpt { match self { RecycleOpt::List(copt) => { let client = copt.to_client(); - let r = client.recycle_bin_list().unwrap(); - for e in r { - println!("{}", e); + match client.recycle_bin_list() { + Ok(r) => r.iter().for_each(|e| println!("{}", e)), + Err(e) => { + eprintln!("Error -> {:?}", e); + } } } RecycleOpt::Get(nopt) => { let client = nopt.copt.to_client(); - let e = client.recycle_bin_get(nopt.name.as_str()).unwrap(); - match e { - Some(e) => println!("{}", e), - None => println!("No matching entries"), + match client.recycle_bin_get(nopt.name.as_str()) { + Ok(Some(e)) => println!("{}", e), + Ok(None) => println!("No matching entries"), + Err(e) => { + eprintln!("Error -> {:?}", e); + } } } RecycleOpt::Revive(nopt) => { 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); + } } } } diff --git a/kanidm_unix_int/nss_kanidm/src/lib.rs b/kanidm_unix_int/nss_kanidm/src/lib.rs index 6a698a08d..87438801d 100644 --- a/kanidm_unix_int/nss_kanidm/src/lib.rs +++ b/kanidm_unix_int/nss_kanidm/src/lib.rs @@ -1,4 +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] extern crate libnss; #[macro_use] diff --git a/kanidm_unix_int/pam_kanidm/src/lib.rs b/kanidm_unix_int/pam_kanidm/src/lib.rs index ecd8f6a75..10b327081 100644 --- a/kanidm_unix_int/pam_kanidm/src/lib.rs +++ b/kanidm_unix_int/pam_kanidm/src/lib.rs @@ -1,5 +1,14 @@ #![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; use crate::pam::constants::*; diff --git a/kanidm_unix_int/src/cache.rs b/kanidm_unix_int/src/cache.rs index 41b4faafd..861045144 100644 --- a/kanidm_unix_int/src/cache.rs +++ b/kanidm_unix_int/src/cache.rs @@ -271,8 +271,12 @@ impl CacheLayer { ClientError::Http( StatusCode::UNAUTHORIZED, Some(OperationError::NotAuthenticated), + opid, ) => { - error!("transport unauthenticated, moving to offline"); + error!( + "transport unauthenticated, moving to offline - eventid {}", + opid + ); // Something went wrong, mark offline. let time = SystemTime::now().add(Duration::from_secs(15)); self.set_cachestate(CacheState::OfflineNextCheck(time)) @@ -282,14 +286,16 @@ impl CacheLayer { ClientError::Http( StatusCode::BAD_REQUEST, Some(OperationError::NoMatchingEntries), + opid, ) | ClientError::Http( StatusCode::BAD_REQUEST, Some(OperationError::InvalidAccountState(_)), + opid, ) => { // We wele able to contact the server but the entry has been removed, or // 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 .map(|tok| self.delete_cache_usertoken(&tok.uuid)) // Now an option> @@ -335,8 +341,12 @@ impl CacheLayer { ClientError::Http( StatusCode::UNAUTHORIZED, Some(OperationError::NotAuthenticated), + opid, ) => { - error!("transport unauthenticated, moving to offline"); + error!( + "transport unauthenticated, moving to offline - eventid {}", + opid + ); // Something went wrong, mark offline. let time = SystemTime::now().add(Duration::from_secs(15)); self.set_cachestate(CacheState::OfflineNextCheck(time)) @@ -346,12 +356,14 @@ impl CacheLayer { ClientError::Http( StatusCode::BAD_REQUEST, Some(OperationError::NoMatchingEntries), + opid, ) | ClientError::Http( StatusCode::BAD_REQUEST, 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 .map(|tok| self.delete_cache_grouptoken(&tok.uuid)) // Now an option> @@ -620,8 +632,12 @@ impl CacheLayer { ClientError::Http( StatusCode::UNAUTHORIZED, Some(OperationError::NotAuthenticated), + opid, ) => { - error!("transport unauthenticated, moving to offline"); + error!( + "transport unauthenticated, moving to offline - eventid {}", + opid + ); // Something went wrong, mark offline. let time = SystemTime::now().add(Duration::from_secs(15)); self.set_cachestate(CacheState::OfflineNextCheck(time)) @@ -634,12 +650,17 @@ impl CacheLayer { ClientError::Http( StatusCode::BAD_REQUEST, Some(OperationError::NoMatchingEntries), + opid, ) | ClientError::Http( StatusCode::BAD_REQUEST, 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) } er => { diff --git a/kanidm_unix_int/src/daemon.rs b/kanidm_unix_int/src/daemon.rs index 1552185d0..4948cbebe 100644 --- a/kanidm_unix_int/src/daemon.rs +++ b/kanidm_unix_int/src/daemon.rs @@ -1,4 +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] extern crate log; diff --git a/kanidm_unix_int/src/db.rs b/kanidm_unix_int/src/db.rs index 572247c75..3f00e0588 100644 --- a/kanidm_unix_int/src/db.rs +++ b/kanidm_unix_int/src/db.rs @@ -7,7 +7,7 @@ use std::convert::TryFrom; use std::fmt; use crate::cache::Id; -use std::sync::{Mutex, MutexGuard}; +use tokio::sync::{Mutex, MutexGuard}; use kanidm::be::dbvalue::DbPasswordV1; use kanidm::credential::Password; diff --git a/kanidm_unix_int/src/lib.rs b/kanidm_unix_int/src/lib.rs index 8b5c86e0d..42598149a 100644 --- a/kanidm_unix_int/src/lib.rs +++ b/kanidm_unix_int/src/lib.rs @@ -1,5 +1,12 @@ #![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] extern crate serde_derive; diff --git a/kanidm_unix_int/tests/cache_layer_test.rs b/kanidm_unix_int/tests/cache_layer_test.rs index a217bb0e8..d0afd80e0 100644 --- a/kanidm_unix_int/tests/cache_layer_test.rs +++ b/kanidm_unix_int/tests/cache_layer_test.rs @@ -101,7 +101,7 @@ fn test_fixture(rsclient: &KanidmClient) -> () { assert!(res.is_ok()); // Not recommended in production! rsclient - .idm_group_add_members("idm_admins", vec!["admin"]) + .idm_group_add_members("idm_admins", &["admin"]) .unwrap(); // Create a new account @@ -126,7 +126,7 @@ fn test_fixture(rsclient: &KanidmClient) -> () { // Setup a group rsclient.idm_group_create("testgroup1").unwrap(); rsclient - .idm_group_add_members("testgroup1", vec!["testaccount1"]) + .idm_group_add_members("testgroup1", &["testaccount1"]) .unwrap(); rsclient .idm_group_unix_extend("testgroup1", Some(20001)) diff --git a/kanidmd/src/lib/idm/account.rs b/kanidmd/src/lib/idm/account.rs index ae891bd1e..b2d13a811 100644 --- a/kanidmd/src/lib/idm/account.rs +++ b/kanidmd/src/lib/idm/account.rs @@ -63,12 +63,12 @@ macro_rules! try_from_entry { let uuid = $value.get_uuid().clone(); Ok(Account { - uuid: uuid, - name: name, - displayname: displayname, - groups: groups, - primary: primary, - spn: spn, + uuid, + name, + displayname, + groups, + primary, + spn, }) }}; } diff --git a/kanidmd/src/lib/lib.rs b/kanidmd/src/lib/lib.rs index 49a24172b..df0ee21e3 100644 --- a/kanidmd/src/lib/lib.rs +++ b/kanidmd/src/lib/lib.rs @@ -1,5 +1,12 @@ #![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] extern crate log;