mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 20:47:01 +01:00
Don't reprompt for login when no session exists in cli (#3082)
* Fix handling when session is already removed so that we don't re-prompt for login. * Remove async recursion
This commit is contained in:
parent
d109622d71
commit
44b93804e6
12
Cargo.lock
generated
12
Cargo.lock
generated
|
@ -259,17 +259,6 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "async-recursion"
|
|
||||||
version = "1.1.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 2.0.79",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-stream"
|
name = "async-stream"
|
||||||
version = "0.3.5"
|
version = "0.3.5"
|
||||||
|
@ -3322,7 +3311,6 @@ name = "kanidm_tools"
|
||||||
version = "1.4.0-dev"
|
version = "1.4.0-dev"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-recursion",
|
|
||||||
"clap",
|
"clap",
|
||||||
"clap_complete",
|
"clap_complete",
|
||||||
"compact_jwt 0.4.2",
|
"compact_jwt 0.4.2",
|
||||||
|
|
|
@ -142,7 +142,6 @@ sketching = { path = "./libs/sketching", version = "=1.4.0-dev" }
|
||||||
anyhow = { version = "1.0.89" }
|
anyhow = { version = "1.0.89" }
|
||||||
argon2 = { version = "0.5.3", features = ["alloc"] }
|
argon2 = { version = "0.5.3", features = ["alloc"] }
|
||||||
askama = { version = "0.12.1", features = ["serde"] }
|
askama = { version = "0.12.1", features = ["serde"] }
|
||||||
async-recursion = "1.1.0"
|
|
||||||
async-trait = "^0.1.83"
|
async-trait = "^0.1.83"
|
||||||
axum = { version = "0.7.7", features = [
|
axum = { version = "0.7.7", features = [
|
||||||
"form",
|
"form",
|
||||||
|
|
|
@ -36,7 +36,6 @@ doctest = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = { workspace = true }
|
anyhow = { workspace = true }
|
||||||
async-recursion = { workspace = true }
|
|
||||||
clap = { workspace = true, features = ["derive", "env"] }
|
clap = { workspace = true, features = ["derive", "env"] }
|
||||||
compact_jwt = { workspace = true, features = ["openssl"] }
|
compact_jwt = { workspace = true, features = ["openssl"] }
|
||||||
dialoguer = { workspace = true }
|
dialoguer = { workspace = true }
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
use async_recursion::async_recursion;
|
|
||||||
use compact_jwt::{traits::JwsVerifiable, JwsCompact, JwsEs256Verifier, JwsVerifier, JwtError};
|
use compact_jwt::{traits::JwsVerifiable, JwsCompact, JwsEs256Verifier, JwsVerifier, JwtError};
|
||||||
use dialoguer::theme::ColorfulTheme;
|
use dialoguer::theme::ColorfulTheme;
|
||||||
use dialoguer::{Confirm, Select};
|
use dialoguer::{Confirm, Select};
|
||||||
|
@ -22,7 +21,7 @@ pub enum OpType {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ToClientError {
|
pub enum ToClientError {
|
||||||
NeedLogin(String),
|
NeedLogin(String),
|
||||||
NeedReauth(String),
|
NeedReauth(String, KanidmClient),
|
||||||
Other,
|
Other,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +97,10 @@ impl CommonOpt {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn try_to_client(&self, optype: OpType) -> Result<KanidmClient, ToClientError> {
|
pub(crate) async fn try_to_client(
|
||||||
|
&self,
|
||||||
|
optype: OpType,
|
||||||
|
) -> Result<KanidmClient, ToClientError> {
|
||||||
let client = self.to_unauth_client();
|
let client = self.to_unauth_client();
|
||||||
|
|
||||||
// Read the token file.
|
// Read the token file.
|
||||||
|
@ -247,6 +249,9 @@ impl CommonOpt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// It's probably valid, set into the client
|
||||||
|
client.set_token(jwsc.to_string()).await;
|
||||||
|
|
||||||
// Check what we are doing based on op.
|
// Check what we are doing based on op.
|
||||||
match optype {
|
match optype {
|
||||||
OpType::Read => {}
|
OpType::Read => {}
|
||||||
|
@ -256,7 +261,7 @@ impl CommonOpt {
|
||||||
"Privileges have expired for {} - you need to re-authenticate again.",
|
"Privileges have expired for {} - you need to re-authenticate again.",
|
||||||
uat.spn
|
uat.spn
|
||||||
);
|
);
|
||||||
return Err(ToClientError::NeedReauth(spn));
|
return Err(ToClientError::NeedReauth(spn, client));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,19 +273,15 @@ impl CommonOpt {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set it into the client
|
|
||||||
client.set_token(jwsc.to_string()).await;
|
|
||||||
|
|
||||||
Ok(client)
|
Ok(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_recursion]
|
|
||||||
pub async fn to_client(&self, optype: OpType) -> KanidmClient {
|
pub async fn to_client(&self, optype: OpType) -> KanidmClient {
|
||||||
|
let mut copt_mut = self.clone();
|
||||||
|
loop {
|
||||||
match self.try_to_client(optype.clone()).await {
|
match self.try_to_client(optype.clone()).await {
|
||||||
Ok(c) => c,
|
Ok(c) => break c,
|
||||||
Err(e) => {
|
Err(ToClientError::NeedLogin(username)) => {
|
||||||
match e {
|
|
||||||
ToClientError::NeedLogin(username) => {
|
|
||||||
if !Confirm::new()
|
if !Confirm::new()
|
||||||
.with_prompt("Would you like to login again?")
|
.with_prompt("Would you like to login again?")
|
||||||
.default(true)
|
.default(true)
|
||||||
|
@ -289,19 +290,19 @@ impl CommonOpt {
|
||||||
{
|
{
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
let mut copt = self.clone();
|
|
||||||
copt.username = Some(username);
|
copt_mut.username = Some(username);
|
||||||
|
let copt = copt_mut.clone();
|
||||||
let login_opt = LoginOpt {
|
let login_opt = LoginOpt {
|
||||||
copt,
|
copt,
|
||||||
password: env::var("KANIDM_PASSWORD").ok(),
|
password: env::var("KANIDM_PASSWORD").ok(),
|
||||||
};
|
};
|
||||||
|
|
||||||
login_opt.exec().await;
|
login_opt.exec().await;
|
||||||
// we still use `to_client` instead of `try_to_client` because we may need to prompt user to re-auth again.
|
// Okay, try again ...
|
||||||
// since reauth_opt will call `to_client`, this function is recursive anyway.
|
continue;
|
||||||
// we use copt since it's username is updated.
|
|
||||||
return login_opt.copt.to_client(optype).await;
|
|
||||||
}
|
}
|
||||||
ToClientError::NeedReauth(username) => {
|
Err(ToClientError::NeedReauth(username, client)) => {
|
||||||
if !Confirm::new()
|
if !Confirm::new()
|
||||||
.with_prompt("Would you like to re-authenticate?")
|
.with_prompt("Would you like to re-authenticate?")
|
||||||
.default(true)
|
.default(true)
|
||||||
|
@ -310,22 +311,18 @@ impl CommonOpt {
|
||||||
{
|
{
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
let mut copt = self.clone();
|
copt_mut.username = Some(username);
|
||||||
copt.username = Some(username);
|
let copt = copt_mut.clone();
|
||||||
let reauth_opt = ReauthOpt { copt };
|
let reauth_opt = ReauthOpt { copt };
|
||||||
// calls `to_client` recursively
|
reauth_opt.inner(client).await;
|
||||||
// but should not goes into `NeedLogin` branch again
|
|
||||||
reauth_opt.exec().await;
|
// Okay, re-auth should have passed, lets loop
|
||||||
if let Ok(c) = reauth_opt.copt.try_to_client(optype).await {
|
continue;
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
}
|
Err(ToClientError::Other) => {
|
||||||
ToClientError::Other => {
|
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::process::exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::common::OpType;
|
use crate::common::{OpType, ToClientError};
|
||||||
use std::cmp::Reverse;
|
use std::cmp::Reverse;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::fs::{create_dir, File};
|
use std::fs::{create_dir, File};
|
||||||
|
@ -569,9 +569,7 @@ impl ReauthOpt {
|
||||||
self.copt.debug
|
self.copt.debug
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn exec(&self) {
|
pub(crate) async fn inner(&self, client: KanidmClient) {
|
||||||
let client = self.copt.to_client(OpType::Read).await;
|
|
||||||
|
|
||||||
let instance_name = &self.copt.instance;
|
let instance_name = &self.copt.instance;
|
||||||
|
|
||||||
let allowed = client.reauth_begin().await.unwrap_or_else(|e| {
|
let allowed = client.reauth_begin().await.unwrap_or_else(|e| {
|
||||||
|
@ -581,6 +579,12 @@ impl ReauthOpt {
|
||||||
|
|
||||||
process_auth_state(allowed, client, &None, instance_name).await;
|
process_auth_state(allowed, client, &None, instance_name).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn exec(&self) {
|
||||||
|
let client = self.copt.to_client(OpType::Read).await;
|
||||||
|
// This is to break a recursion loop in re-auth with to_client
|
||||||
|
self.inner(client).await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LogoutOpt {
|
impl LogoutOpt {
|
||||||
|
@ -626,7 +630,18 @@ impl LogoutOpt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let client = self.copt.to_client(OpType::Read).await;
|
let client = match self.copt.try_to_client(OpType::Read).await {
|
||||||
|
Ok(c) => c,
|
||||||
|
Err(ToClientError::NeedLogin(_)) => {
|
||||||
|
// There are no session tokens, so return a success.
|
||||||
|
std::process::exit(0);
|
||||||
|
}
|
||||||
|
Err(ToClientError::NeedReauth(_, _)) | Err(ToClientError::Other) => {
|
||||||
|
// This can only occur in bad cases, so fail.
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let token = match client.get_token().await {
|
let token = match client.get_token().await {
|
||||||
Some(t) => t,
|
Some(t) => t,
|
||||||
None => {
|
None => {
|
||||||
|
|
Loading…
Reference in a new issue