Private
Public Access
1
0

daemon: adds conversation list limit, fixes auth saving in db auth store

This commit is contained in:
2025-05-03 18:19:48 -07:00
parent 26d54f91d5
commit 0d61b6f2d7
13 changed files with 69 additions and 37 deletions

View File

@@ -5,8 +5,8 @@ use async_trait::async_trait;
#[async_trait]
pub trait AuthenticationStore {
async fn get_credentials(&mut self) -> Option<Credentials>;
async fn get_token(&mut self) -> Option<JwtToken>;
async fn set_token(&mut self, token: JwtToken);
async fn get_token(&mut self) -> Option<String>;
async fn set_token(&mut self, token: String);
}
pub struct InMemoryAuthenticationStore {
@@ -35,11 +35,11 @@ impl AuthenticationStore for InMemoryAuthenticationStore {
self.credentials.clone()
}
async fn get_token(&mut self) -> Option<JwtToken> {
self.token.clone()
async fn get_token(&mut self) -> Option<String> {
self.token.clone().map(|token| token.to_string())
}
async fn set_token(&mut self, token: JwtToken) {
self.token = Some(token);
async fn set_token(&mut self, token: String) {
self.token = Some(JwtToken::new(&token).unwrap());
}
}

View File

@@ -92,6 +92,7 @@ impl From <tungstenite::Error> for Error {
trait AuthBuilder {
fn with_auth(self, token: &Option<JwtToken>) -> Self;
fn with_auth_string(self, token: &Option<String>) -> Self;
}
impl AuthBuilder for hyper::http::request::Builder {
@@ -100,6 +101,12 @@ impl AuthBuilder for hyper::http::request::Builder {
self.header("Authorization", token.to_header_value())
} else { self }
}
fn with_auth_string(self, token: &Option<String>) -> Self {
if let Some(token) = &token {
self.header("Authorization", format!("Bearer: {}", token))
} else { self }
}
}
#[cfg(test)]
@@ -196,7 +203,7 @@ impl<K: AuthenticationStore + Send + Sync> APIInterface for HTTPAPIClient<K> {
let token = JwtToken::new(&token.jwt).map_err(|e| Error::DecodeError(e.to_string()))?;
log::debug!("Saving token: {:?}", token);
self.auth_store.set_token(token.clone()).await;
self.auth_store.set_token(token.to_string()).await;
Ok(token)
}
@@ -261,8 +268,7 @@ impl<K: AuthenticationStore + Send + Sync> APIInterface for HTTPAPIClient<K> {
match &auth {
Some(token) => {
let header_value = token.to_header_value().to_str().unwrap().parse().unwrap(); // ugh
request.headers_mut().insert("Authorization", header_value);
request.headers_mut().insert("Authorization", format!("Bearer: {}", token).parse().unwrap());
}
None => {
log::warn!(target: "websocket", "Proceeding without auth token.");
@@ -276,14 +282,14 @@ impl<K: AuthenticationStore + Send + Sync> APIInterface for HTTPAPIClient<K> {
log::debug!("Websocket connected: {:?}", response.status());
Ok(WebsocketEventSocket::new(socket))
}
Err(e) => match e {
Err(e) => match &e {
Error::ClientError(ce) => match ce.as_str() {
"HTTP error: 401 Unauthorized" | "Unauthorized" => {
// Try to authenticate
if let Some(credentials) = &self.auth_store.get_credentials().await {
log::warn!("Websocket connection failed, attempting to authenticate");
let new_token = self.authenticate(credentials.clone()).await?;
self.auth_store.set_token(new_token).await;
self.auth_store.set_token(new_token.to_string()).await;
// try again on the next attempt.
return Err(Error::Unauthorized);
@@ -292,7 +298,7 @@ impl<K: AuthenticationStore + Send + Sync> APIInterface for HTTPAPIClient<K> {
return Err(Error::ClientError("Unauthorized, no credentials provided".into()));
}
}
_ => Err(Error::Unauthorized)
_ => Err(e)
}
_ => Err(e)
@@ -355,12 +361,12 @@ impl<K: AuthenticationStore + Send + Sync> HTTPAPIClient<K> {
let uri = self.uri_for_endpoint(endpoint, None);
log::debug!("Requesting {:?} {:?}", method, uri);
let build_request = move |auth: &Option<JwtToken>| {
let build_request = move |auth: &Option<String>| {
let body = body_fn();
Request::builder()
.method(&method)
.uri(&uri)
.with_auth(auth)
.with_auth_string(auth)
.body(body)
.expect("Unable to build request")
};
@@ -384,7 +390,7 @@ impl<K: AuthenticationStore + Send + Sync> HTTPAPIClient<K> {
log::debug!("Renewing token using credentials: u: {:?}", credentials.username);
let new_token = self.authenticate(credentials.clone()).await?;
let request = build_request(&Some(new_token));
let request = build_request(&Some(new_token.to_string()));
response = self.client.request(request).await?;
} else {
return Err(Error::ClientError("Unauthorized, no credentials provided".into()));

View File

@@ -137,4 +137,8 @@ impl JwtToken {
pub fn to_header_value(&self) -> HeaderValue {
format!("Bearer {}", self.token).parse().unwrap()
}
pub fn to_string(&self) -> String {
self.token.clone()
}
}