allow setting tasmota credentials

This commit is contained in:
Robin Appelman 2022-07-24 22:34:48 +02:00
commit 3f583617b4
4 changed files with 61 additions and 5 deletions

1
Cargo.lock generated
View file

@ -1124,6 +1124,7 @@ name = "tasproxy"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"async-stream", "async-stream",
"base64",
"color-eyre", "color-eyre",
"dashmap", "dashmap",
"dotenv", "dotenv",

View file

@ -20,3 +20,4 @@ pin-utils = "0.1"
hostname = "0.3" hostname = "0.3"
warp-reverse-proxy = { version = "0.3", default_features = false, features = ["rustls-tls"] } warp-reverse-proxy = { version = "0.3", default_features = false, features = ["rustls-tls"] }
tokio-stream = { version = "0.1.9", features = ["net"] } tokio-stream = { version = "0.1.9", features = ["net"] }
base64 = "0.13.0"

View file

@ -8,6 +8,7 @@ pub struct Config {
pub mqtt_port: u16, pub mqtt_port: u16,
pub mqtt_credentials: Option<Credentials>, pub mqtt_credentials: Option<Credentials>,
pub listen: Listen, pub listen: Listen,
pub tasmota_credentials: Option<Credentials>,
} }
#[derive(Clone)] #[derive(Clone)]
@ -16,9 +17,22 @@ pub enum Listen {
Unix(String), Unix(String),
} }
#[derive(Clone)]
pub struct Credentials { pub struct Credentials {
username: String, pub username: String,
password: String, pub password: String,
}
impl Credentials {
pub fn auth_header(&self) -> String {
let mut header = "Basic ".to_string();
base64::encode_config_buf(
format!("{}:{}", self.username, self.password),
base64::STANDARD,
&mut header,
);
header
}
} }
impl Config { impl Config {
@ -48,10 +62,20 @@ impl Config {
Err(_) => None, Err(_) => None,
}; };
let tasmota_credentials = match dotenv::var("TASMOTA_USERNAME") {
Ok(username) => {
let password = dotenv::var("TASMOTA_PASSWORD")
.wrap_err("TASMOTA_USERNAME set, but TASMOTA_PASSWORD not set")?;
Some(Credentials { username, password })
}
Err(_) => None,
};
Ok(Config { Ok(Config {
mqtt_host, mqtt_host,
mqtt_port, mqtt_port,
mqtt_credentials, mqtt_credentials,
tasmota_credentials,
listen, listen,
}) })
} }

View file

@ -16,9 +16,14 @@ use tokio::net::UnixListener;
use tokio::signal; use tokio::signal;
use tokio::time::sleep; use tokio::time::sleep;
use tokio_stream::wrappers::UnixListenerStream; use tokio_stream::wrappers::UnixListenerStream;
use warp::http::{HeaderMap, HeaderValue, Method};
use warp::hyper::body::Bytes;
use warp::hyper::http::uri::Authority; use warp::hyper::http::uri::Authority;
use warp::path::FullPath;
use warp::Filter; use warp::Filter;
use warp_reverse_proxy::{extract_request_data_filter, proxy_to_and_forward_response}; use warp_reverse_proxy::{
extract_request_data_filter, proxy_to_and_forward_response, QueryParameters,
};
mod config; mod config;
mod devices; mod devices;
@ -31,6 +36,10 @@ type DeviceStates = Arc<DashMap<String, DeviceState>>;
async fn main() -> Result<()> { async fn main() -> Result<()> {
let config = Config::from_env()?; let config = Config::from_env()?;
let listen = config.listen.clone(); let listen = config.listen.clone();
let tasmota_credentails = config
.tasmota_credentials
.as_ref()
.map(|auth| auth.auth_header());
let device_states = DeviceStates::default(); let device_states = DeviceStates::default();
@ -76,7 +85,28 @@ async fn main() -> Result<()> {
) )
.untuple_one() .untuple_one()
.and(extract_request_data_filter()) .and(extract_request_data_filter())
.and_then(proxy_to_and_forward_response); .and_then(
move |proxy_address: String,
base_path: String,
uri: FullPath,
params: QueryParameters,
method: Method,
mut headers: HeaderMap,
body: Bytes| {
if let Some(credentials) = tasmota_credentails.as_deref() {
headers.append("authorization", HeaderValue::from_str(credentials).unwrap());
}
proxy_to_and_forward_response(
proxy_address,
base_path,
uri,
params,
method,
headers,
body,
)
},
);
let cancel = async { let cancel = async {
signal::ctrl_c().await.ok(); signal::ctrl_c().await.ok();