fix: allow using self-signed certs

Closes https://github.com/etiennecollin/unifi-voucher-manager/issues/3
This commit is contained in:
etiennecollin
2025-08-15 09:21:43 -04:00
parent 40edea1d74
commit 0f0a0cc51a
7 changed files with 70 additions and 27 deletions

View File

@@ -20,6 +20,7 @@ pub struct Environment {
pub unifi_api_key: String,
pub backend_bind_host: String,
pub backend_bind_port: u16,
pub unifi_has_valid_cert: bool,
pub timezone: Tz,
}
@@ -30,6 +31,13 @@ impl Environment {
let unifi_controller_url: String =
env::var("UNIFI_CONTROLLER_URL").map_err(|e| format!("UNIFI_CONTROLLER_URL: {e}"))?;
if !unifi_controller_url.starts_with("http://")
&& !unifi_controller_url.starts_with("https://")
{
return Err("UNIFI_CONTROLLER_URL must start with http:// or https://".to_string());
}
let unifi_api_key: String =
env::var("UNIFI_API_KEY").map_err(|e| format!("UNIFI_API_KEY: {e}"))?;
let unifi_site_id: String =
@@ -44,6 +52,17 @@ impl Environment {
Err(_) => DEFAULT_BACKEND_BIND_PORT,
};
let unifi_has_valid_cert: bool = match env::var("UNIFI_HAS_VALID_CERT") {
Ok(val) => match val.trim().to_lowercase().as_str() {
"true" | "1" | "yes" => true,
"false" | "0" | "no" => false,
_ => {
return Err("Invalid UNIFI_HAS_VALID_CERT, must be true/false".to_string());
}
},
Err(_) => true,
};
let timezone: Tz = match env::var("TIMEZONE") {
Ok(s) => match s.parse() {
Ok(tz) => {
@@ -67,6 +86,7 @@ impl Environment {
unifi_api_key,
backend_bind_host,
backend_bind_port,
unifi_has_valid_cert,
timezone,
})
}

View File

@@ -2,7 +2,7 @@ use chrono::DateTime;
use chrono_tz::Tz;
use reqwest::{Client, ClientBuilder, StatusCode};
use std::{sync::OnceLock, time::Duration};
use tracing::{error, info, warn};
use tracing::{debug, error, info, warn};
use crate::{
ENVIRONMENT, Environment,
@@ -52,6 +52,7 @@ impl<'a> UnifiAPI<'a> {
.timeout(Duration::from_secs(30))
.connect_timeout(Duration::from_secs(10))
.default_headers(headers)
.danger_accept_invalid_certs(!environment.unifi_has_valid_cert)
.use_rustls_tls()
.build()
.expect("Failed to build UniFi reqwest client");
@@ -113,7 +114,11 @@ impl<'a> UnifiAPI<'a> {
Ok(resp) => resp,
Err(e) => {
let status = e.status().unwrap_or(StatusCode::INTERNAL_SERVER_ERROR);
error!("Request failed with status {}: {}", status, e.without_url());
error!(
"Request failed with status {}: {:?}",
status,
e.without_url()
);
return Err(status);
}
};
@@ -134,9 +139,24 @@ impl<'a> UnifiAPI<'a> {
}
};
// It's a successful response, now parse the JSON
clean_response.json::<U>().await.map_err(|e| {
error!("Failed to parse response JSON: {}", e);
// It's a successful response, now get the response body
let response_text = clean_response.text().await.map_err(|e| {
error!("Failed to read response body: {:?}", e);
StatusCode::INTERNAL_SERVER_ERROR
})?;
// Parse the response body as JSON
let response_json: serde_json::Value =
serde_json::from_str(&response_text).map_err(|e| {
error!("Failed to parse response body as JSON: {:?}", e);
debug!("Response body: {}", response_text);
StatusCode::INTERNAL_SERVER_ERROR
})?;
// Parse the JSON into the expected structure
serde_json::from_value::<U>(response_json).map_err(|e| {
error!("Failed to parse response JSON structure: {:?}", e);
debug!("Response body: {}", response_text);
StatusCode::INTERNAL_SERVER_ERROR
})
}