Refine WireGuard client routing and authentication UI
This commit is contained in:
1 parent
eabb3e4472
commit
41fb9d5631
33 files changed
+1709
-469
No files matched your search
@@ -11,6 +11,8 @@ pub struct Line {
|
||||
pub remark: String,
|
||||
pub state: String,
|
||||
pub endpoint: String,
|
||||
#[serde(default)]
|
||||
pub routing_mode: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@@ -21,6 +23,15 @@ pub struct LoginResult {
|
||||
pub lines: Vec<Line>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ClientCapabilities {
|
||||
pub password: bool,
|
||||
pub oidc: bool,
|
||||
#[serde(default)]
|
||||
pub oidc_provider: Option<String>,
|
||||
pub wireguard: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct DeviceConfig {
|
||||
pub device_id: u64,
|
||||
@@ -33,6 +44,8 @@ pub struct DeviceConfig {
|
||||
pub preshared_key: String,
|
||||
pub endpoint: String,
|
||||
pub allowed_ips: String,
|
||||
#[serde(default)]
|
||||
pub latency_probe: String,
|
||||
pub dns: String,
|
||||
pub mtu: u32,
|
||||
pub keepalive: u32,
|
||||
@@ -143,13 +156,8 @@ pub async fn login(
|
||||
device_name: &str,
|
||||
) -> Result<LoginResult, ApiError> {
|
||||
// 旧版服务端会把未知 /api/client/* 路径返回 200 HTML;先确认能力,避免发送密码。
|
||||
let capabilities = client()?
|
||||
.get(api_url(base_url, "/api/client/capabilities")?)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| ApiError::Transport(format!("连接服务端失败:{err}")))?;
|
||||
let supported: serde_json::Value = parse_response(capabilities).await?;
|
||||
if supported.get("password").and_then(|v| v.as_bool()) != Some(true) {
|
||||
let supported = capabilities(base_url).await?;
|
||||
if !supported.password {
|
||||
return Err(ApiError::Transport("服务端尚未启用客户端密码登录".into()));
|
||||
}
|
||||
let resp = client()?
|
||||
@@ -167,6 +175,15 @@ pub async fn login(
|
||||
parse_response(resp).await
|
||||
}
|
||||
|
||||
pub async fn capabilities(base_url: &str) -> Result<ClientCapabilities, ApiError> {
|
||||
let response = client()?
|
||||
.get(api_url(base_url, "/api/client/capabilities")?)
|
||||
.send()
|
||||
.await
|
||||
.map_err(|err| ApiError::Transport(format!("连接服务端失败:{err}")))?;
|
||||
parse_response(response).await
|
||||
}
|
||||
|
||||
pub async fn logout(base_url: &str, token: &str) -> Result<(), ApiError> {
|
||||
let resp = client()?
|
||||
.post(api_url(base_url, "/api/client/logout")?)
|
||||
@@ -292,4 +309,19 @@ mod tests {
|
||||
);
|
||||
assert!(api_url("ftp://vpn.example.com", "/api/client/lines").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn client_auth_capabilities_accept_legacy_and_provider_specific_responses() {
|
||||
let current: ClientCapabilities = serde_json::from_str(
|
||||
r#"{"password":true,"oidc":false,"wireguard":true}"#,
|
||||
).unwrap();
|
||||
assert!(current.password);
|
||||
assert!(!current.oidc);
|
||||
assert!(current.oidc_provider.is_none());
|
||||
let future: ClientCapabilities = serde_json::from_str(
|
||||
r#"{"password":false,"oidc":true,"oidc_provider":"feishu","wireguard":true}"#,
|
||||
).unwrap();
|
||||
assert!(!future.password);
|
||||
assert_eq!(future.oidc_provider.as_deref(), Some("feishu"));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user