apply authentication data to requests
This commit is contained in:
@ -157,6 +157,14 @@ impl Subscription {
|
|||||||
.append_pair("since", &since.to_string());
|
.append_pair("since", &since.to_string());
|
||||||
Ok(url)
|
Ok(url)
|
||||||
}
|
}
|
||||||
|
pub fn build_auth_url(server: &str, topic: &str) -> Result<url::Url, crate::Error> {
|
||||||
|
let mut url = url::Url::parse(server)?;
|
||||||
|
url.path_segments_mut()
|
||||||
|
.map_err(|_| url::ParseError::RelativeUrlWithCannotBeABaseBase)?
|
||||||
|
.push(topic)
|
||||||
|
.push("auth");
|
||||||
|
Ok(url)
|
||||||
|
}
|
||||||
pub fn validate(self) -> Result<Self, Vec<crate::Error>> {
|
pub fn validate(self) -> Result<Self, Vec<crate::Error>> {
|
||||||
let mut errs = vec![];
|
let mut errs = vec![];
|
||||||
if let Err(e) = validate_topic(&self.topic) {
|
if let Err(e) = validate_topic(&self.topic) {
|
||||||
|
|||||||
@ -493,8 +493,7 @@ impl system_notifier::Server for SystemNotifier {
|
|||||||
let password = params.get()?.get_password()?.to_str()?;
|
let password = params.get()?.get_password()?.to_str()?;
|
||||||
|
|
||||||
info!("validating account");
|
info!("validating account");
|
||||||
let url = models::Subscription::build_url(server, "stats", 0)
|
let url = models::Subscription::build_auth_url(server, "stats")?;
|
||||||
.map_err(|e| capnp::Error::failed(e.to_string()))?;
|
|
||||||
|
|
||||||
http.get(url)
|
http.get(url)
|
||||||
.basic_auth(username, Some(password))
|
.basic_auth(username, Some(password))
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
use std::ops::ControlFlow;
|
use std::ops::ControlFlow;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
@ -61,16 +62,24 @@ pub fn build_client() -> anyhow::Result<reqwest::Client> {
|
|||||||
.build()?)
|
.build()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn topic_request(endpoint: &str, topic: &str, since: u64) -> anyhow::Result<reqwest::Request> {
|
fn topic_request(
|
||||||
|
client: &reqwest::Client,
|
||||||
|
endpoint: &str,
|
||||||
|
topic: &str,
|
||||||
|
since: u64,
|
||||||
|
username: Option<&str>,
|
||||||
|
password: Option<&str>,
|
||||||
|
) -> anyhow::Result<reqwest::Request> {
|
||||||
let url = models::Subscription::build_url(endpoint, topic, since)?;
|
let url = models::Subscription::build_url(endpoint, topic, since)?;
|
||||||
let mut req = reqwest::Request::new(reqwest::Method::GET, url);
|
let mut req = client
|
||||||
let headers = req.headers_mut();
|
.get(url)
|
||||||
headers.append(
|
.header("Content-Type", "application/x-ndjson")
|
||||||
"Content-Type",
|
.header("Transfer-Encoding", "chunked");
|
||||||
HeaderValue::from_static("application/x-ndjson"),
|
if let Some(username) = username {
|
||||||
);
|
req = req.basic_auth(username, password);
|
||||||
headers.append("Transfer-Encoding", HeaderValue::from_static("chunked"));
|
}
|
||||||
Ok(req)
|
|
||||||
|
Ok(req.build()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn response_lines(
|
async fn response_lines(
|
||||||
@ -161,8 +170,36 @@ impl TopicListener {
|
|||||||
|
|
||||||
#[instrument(skip_all)]
|
#[instrument(skip_all)]
|
||||||
async fn recv_and_forward(&mut self) -> anyhow::Result<()> {
|
async fn recv_and_forward(&mut self) -> anyhow::Result<()> {
|
||||||
let req = topic_request(&self.endpoint, &self.topic, self.since)?;
|
let (username, password) = {
|
||||||
let res = self.env.http.execute(req).await?;
|
let attrs = HashMap::from([("type", "password"), ("server", &self.endpoint)]);
|
||||||
|
let items = self
|
||||||
|
.env
|
||||||
|
.keyring
|
||||||
|
.search_items(attrs)
|
||||||
|
.await
|
||||||
|
.map_err(|e| capnp::Error::failed(e.to_string()))?;
|
||||||
|
|
||||||
|
if let Some(item) = items.into_iter().next() {
|
||||||
|
let attrs = item
|
||||||
|
.attributes()
|
||||||
|
.await
|
||||||
|
.map_err(|e| capnp::Error::failed(e.to_string()))?;
|
||||||
|
let password = item.secret().await?;
|
||||||
|
let password = std::str::from_utf8(&*password)?;
|
||||||
|
(attrs.get("username").cloned(), Some(password.to_string()))
|
||||||
|
} else {
|
||||||
|
(None, None)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let req = topic_request(
|
||||||
|
&self.env.http,
|
||||||
|
&self.endpoint,
|
||||||
|
&self.topic,
|
||||||
|
self.since,
|
||||||
|
username.as_deref(),
|
||||||
|
password.as_deref(),
|
||||||
|
);
|
||||||
|
let res = self.env.http.execute(req?).await?;
|
||||||
let reader = tokio_util::io::StreamReader::new(
|
let reader = tokio_util::io::StreamReader::new(
|
||||||
res.bytes_stream()
|
res.bytes_stream()
|
||||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string())),
|
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string())),
|
||||||
|
|||||||
Reference in New Issue
Block a user