Support connect gateway

This commit is contained in:
Kevin Yue 2024-01-26 22:35:53 -05:00
parent aac401e7ee
commit e6994d5733
6 changed files with 85 additions and 24 deletions

View File

@ -141,6 +141,16 @@ impl CachedCredential {
}
}
impl From<PasswordCredential> for CachedCredential {
fn from(value: PasswordCredential) -> Self {
Self::new(
value.username().to_owned(),
Some(value.password().to_owned()),
AuthCookieCredential::new("", "", ""),
)
}
}
#[derive(Debug, Serialize, Deserialize, Type, Clone)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum Credential {

View File

@ -22,11 +22,15 @@ pub async fn gateway_login(
params.extend(extra_params);
params.insert("server", gateway);
info!("Gateway login params {:?}", params);
info!("Gateway login, user_agent: {}", gp_params.user_agent());
let res = client.post(&login_url).form(&params).send().await?;
let res_xml = res.error_for_status()?.text().await?;
info!("Gateway login request done");
let doc = Document::parse(&res_xml)?;
build_gateway_token(&doc, gp_params.computer())

View File

@ -31,6 +31,15 @@ impl Display for Gateway {
}
impl Gateway {
pub fn new(name: String, address: String) -> Self {
Self {
name,
address,
priority: 0,
priority_rules: vec![],
}
}
pub fn name(&self) -> &str {
&self.name
}

View File

@ -1,15 +1,15 @@
use anyhow::ensure;
use anyhow::bail;
use log::info;
use reqwest::Client;
use reqwest::{Client, StatusCode};
use roxmltree::Document;
use serde::Serialize;
use specta::Type;
use thiserror::Error;
use crate::{
credential::{AuthCookieCredential, Credential},
gateway::{parse_gateways, Gateway},
gp_params::GpParams,
portal::PortalError,
utils::{normalize_server, xml},
};
@ -98,12 +98,6 @@ impl PortalConfig {
}
}
#[derive(Error, Debug)]
pub enum PortalConfigError {
#[error("Empty response, retrying can help")]
EmptyResponse,
}
pub async fn retrieve_config(
portal: &str,
cred: &Credential,
@ -127,14 +121,35 @@ pub async fn retrieve_config(
info!("Portal config, user_agent: {}", gp_params.user_agent());
info!("Portal config params: {:?}", params);
let res = client.post(&url).form(&params).send().await?;
let res_xml = res.error_for_status()?.text().await?;
let status = res.status();
ensure!(!res_xml.is_empty(), PortalConfigError::EmptyResponse);
if status == StatusCode::NOT_FOUND {
bail!(PortalError::ConfigError(
"Config endpoint not found".to_string()
))
}
let doc = Document::parse(&res_xml)?;
let mut gateways =
parse_gateways(&doc).ok_or_else(|| anyhow::anyhow!("Failed to parse gateways"))?;
let res_xml = res
.error_for_status()?
.text()
.await
.map_err(|e| PortalError::ConfigError(e.to_string()))?;
if res_xml.is_empty() {
bail!(PortalError::ConfigError(
"Empty portal config response".to_string()
))
}
let doc = Document::parse(&res_xml).map_err(|e| PortalError::ConfigError(e.to_string()))?;
let mut gateways = parse_gateways(&doc).unwrap_or_else(|| {
info!("No gateways found in portal config");
vec![]
});
let user_auth_cookie = xml::get_child_text(&doc, "portal-userauthcookie").unwrap_or_default();
let prelogon_user_auth_cookie =
@ -142,12 +157,7 @@ pub async fn retrieve_config(
let config_digest = xml::get_child_text(&doc, "config-digest");
if gateways.is_empty() {
gateways.push(Gateway {
name: server.to_string(),
address: server.to_string(),
priority: 0,
priority_rules: vec![],
});
gateways.push(Gateway::new(server.to_string(), server.to_string()));
}
Ok(PortalConfig::new(

View File

@ -3,3 +3,13 @@ mod prelogin;
pub use config::*;
pub use prelogin::*;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum PortalError {
#[error("Portal prelogin error: {0}")]
PreloginError(String),
#[error("Portal config error: {0}")]
ConfigError(String),
}

View File

@ -1,12 +1,13 @@
use anyhow::bail;
use log::{info, trace};
use reqwest::Client;
use log::info;
use reqwest::{Client, StatusCode};
use roxmltree::Document;
use serde::Serialize;
use specta::Type;
use crate::{
gp_params::GpParams,
portal::PortalError,
utils::{base64, normalize_server, xml},
};
@ -118,9 +119,26 @@ pub async fn prelogin(portal: &str, gp_params: &GpParams) -> anyhow::Result<Prel
.build()?;
let res = client.post(&prelogin_url).form(&params).send().await?;
let res_xml = res.error_for_status()?.text().await?;
let status = res.status();
trace!("Prelogin response: {}", res_xml);
if status == StatusCode::NOT_FOUND {
bail!(PortalError::PreloginError(
"Prelogin endpoint not found".to_string()
))
}
let res_xml = res
.error_for_status()?
.text()
.await
.map_err(|e| PortalError::PreloginError(e.to_string()))?;
let prelogin = parse_res_xml(res_xml).map_err(|e| PortalError::PreloginError(e.to_string()))?;
Ok(prelogin)
}
fn parse_res_xml(res_xml: String) -> anyhow::Result<Prelogin> {
let doc = Document::parse(&res_xml)?;
let status = xml::get_child_text(&doc, "status")