commit 09c82b01c23c8f36a0d7fb247ee76b63a7911477
parent 94108195cdffce537bc2180563a9c6a530b7829b
Author: Marcel <mtrnord1@gmail.com>
Date: Sat, 4 Jul 2020 12:30:27 +0200
Move login logic to a seperate file
Took 2 hours 42 minutes
Diffstat:
4 files changed, 185 insertions(+), 166 deletions(-)
diff --git a/src/app/matrix/login.rs b/src/app/matrix/login.rs
@@ -0,0 +1,75 @@
+use crate::errors::{Field, MatrixError};
+use log::*;
+use matrix_sdk::{Client, ClientConfig, Session};
+use serde::{Deserialize, Serialize};
+use std::convert::TryFrom;
+use url::Url;
+use wasm_bindgen_futures::spawn_local;
+
+#[derive(Serialize, Deserialize, Default, Clone, Debug)]
+pub struct SessionStore {
+ pub(crate) access_token: String,
+ pub(crate) user_id: String,
+ pub(crate) device_id: String,
+ pub(crate) homeserver_url: String,
+}
+
+pub fn login(
+ session: Option<&SessionStore>,
+ homeserver: Option<&String>,
+) -> Result<Client, MatrixError> {
+ info!("preparing client");
+ match session {
+ Some(session) => restore_client(session),
+ None => match homeserver {
+ Some(homeserver) => {
+ let homeserver = Url::parse(&homeserver);
+ match homeserver {
+ Ok(homeserver) => {
+ let client_config = ClientConfig::new();
+ let client = Client::new_with_config(homeserver, client_config).unwrap();
+ Ok(client)
+ }
+ Err(e) => Err(MatrixError::UrlParseError(e.to_string())),
+ }
+ }
+ None => Err(MatrixError::MissingFields(Field::Homeserver)),
+ },
+ }
+}
+
+fn restore_client(session: &SessionStore) -> Result<Client, MatrixError> {
+ let homeserver = Url::parse(&session.homeserver_url);
+ match homeserver {
+ Ok(homeserver) => {
+ let client_config = ClientConfig::new();
+ let client = Client::new_with_config(homeserver, client_config);
+ match client {
+ Ok(client) => {
+ info!("got client");
+ // Also directly restore Login data
+ let session = Session {
+ access_token: session.access_token.clone(),
+ user_id: matrix_sdk::identifiers::UserId::try_from(
+ session.user_id.as_str(),
+ )
+ .unwrap(),
+ device_id: session.device_id.clone(),
+ };
+ info!("before restore");
+ let cloned_client = client.clone();
+ spawn_local(async move {
+ if let Err(e) = cloned_client.restore_login(session).await {
+ error!("{}", e);
+ // TODO find a way to get this back up in the function tree
+ }
+ });
+ info!("after restore");
+ Ok(client)
+ }
+ Err(e) => Err(MatrixError::SDKError(e.to_string())),
+ }
+ }
+ Err(e) => Err(MatrixError::UrlParseError(e.to_string())),
+ }
+}
diff --git a/src/app/matrix/mod.rs b/src/app/matrix/mod.rs
@@ -1,5 +1,4 @@
use std::collections::HashSet;
-use std::convert::TryFrom;
use std::sync::Arc;
use log::*;
@@ -16,17 +15,18 @@ use matrix_sdk::{
identifiers::RoomId,
js_int::UInt,
locks::RwLock,
- Client, ClientConfig, MessagesRequestBuilder, Room, Session,
+ Client, MessagesRequestBuilder, Room,
};
use pulldown_cmark::{html, Options, Parser};
use serde::{Deserialize, Serialize};
-use url::Url;
use wasm_bindgen_futures::spawn_local;
use yew::worker::*;
use crate::app::matrix::types::{get_media_download_url, get_video_media_download_url};
-use crate::errors::{Field, MatrixError};
+use crate::errors::MatrixError;
+use login::{login, SessionStore};
+pub mod login;
mod sync;
pub mod types;
@@ -37,14 +37,6 @@ pub struct MatrixClient {
pub(crate) password: Option<String>,
}
-#[derive(Serialize, Deserialize, Default, Clone, Debug)]
-pub struct SessionStore {
- pub(crate) access_token: String,
- pub(crate) user_id: String,
- pub(crate) device_id: String,
- pub(crate) homeserver_url: String,
-}
-
#[derive(Clone, Debug)]
pub struct MatrixAgent {
link: AgentLink<MatrixAgent>,
@@ -134,117 +126,124 @@ impl Agent for MatrixAgent {
}
Request::Login => {
info!("Starting Login");
- let login_client = self.login();
- if login_client.is_none() {
- for sub in self.subscribers.iter() {
- let resp = Response::Error(MatrixError::MissingClient);
- self.link.respond(*sub, resp);
- }
- return;
- }
- let client = login_client.unwrap();
- let username = self.matrix_state.username.clone().unwrap();
- let password = self.matrix_state.password.clone().unwrap();
- let subscribers = self.subscribers.clone();
- let agent = self.clone();
- spawn_local(async move {
- // TODO handle login error
- if agent.session.is_some() {
- let stored_session = agent.session.unwrap();
- let session = Session {
- access_token: stored_session.access_token,
- user_id: matrix_sdk::identifiers::UserId::try_from(
- stored_session.user_id.as_str(),
- )
- .unwrap(),
- device_id: stored_session.device_id,
- };
- client.restore_login(session).await;
- } else {
- // FIXME gracefully handle login errors
- let login_response = client
- .login(username, password, None, Some("Daydream".to_string()))
- .await;
- match login_response {
- Ok(login_response) => {
- let session_store = SessionStore {
- access_token: login_response.access_token,
- user_id: login_response.user_id.to_string(),
- device_id: login_response.device_id,
- homeserver_url: client.homeserver().to_string(),
- };
- for sub in subscribers.iter() {
- let resp = Response::SaveSession(session_store.clone());
- agent.link.respond(*sub, resp);
- let resp = Response::LoggedIn(true);
- agent.link.respond(*sub, resp);
- }
+ let homeserver = self.matrix_state.homeserver.as_ref();
+ let session = self.session.as_ref();
+ let client = login(session, homeserver);
+ match client {
+ Ok(client) => {
+ if let Some(_session) = session {
+ for sub in self.subscribers.iter() {
+ let resp = Response::LoggedIn(true);
+ self.link.respond(*sub, resp);
}
- Err(e) => {
- if let matrix_sdk::Error::Reqwest(e) = e {
- match e.status() {
- None => {
- for sub in subscribers.iter() {
- let resp = Response::Error(MatrixError::SDKError(
- e.to_string(),
- ));
- agent.link.respond(*sub, resp);
- }
- }
- Some(v) => {
- if v.is_server_error() {
- for sub in subscribers.iter() {
- let resp =
- Response::Error(MatrixError::LoginTimeout);
- agent.link.respond(*sub, resp);
- }
- } else {
- for sub in subscribers.iter() {
+ }
+ self.matrix_client = Some(client.clone());
+ let username = self.matrix_state.username.clone().unwrap();
+ let password = self.matrix_state.password.clone().unwrap();
+ let agent = self.clone();
+ spawn_local(async move {
+ // FIXME gracefully handle login errors
+ let login_response = agent
+ .matrix_client
+ .as_ref()
+ .unwrap()
+ .login(username, password, None, Some("Daydream".to_string()))
+ .await;
+ match login_response {
+ Ok(login_response) => {
+ let session_store = SessionStore {
+ access_token: login_response.access_token,
+ user_id: login_response.user_id.to_string(),
+ device_id: login_response.device_id,
+ homeserver_url: client.homeserver().to_string(),
+ };
+ for sub in agent.subscribers.iter() {
+ let resp = Response::SaveSession(session_store.clone());
+ agent.link.respond(*sub, resp);
+ let resp = Response::LoggedIn(true);
+ agent.link.respond(*sub, resp);
+ }
+ }
+ Err(e) => {
+ if let matrix_sdk::Error::Reqwest(e) = e {
+ match e.status() {
+ None => {
+ for sub in agent.subscribers.iter() {
let resp = Response::Error(
MatrixError::SDKError(e.to_string()),
);
agent.link.respond(*sub, resp);
}
}
+ Some(v) => {
+ if v.is_server_error() {
+ for sub in agent.subscribers.iter() {
+ let resp = Response::Error(
+ MatrixError::LoginTimeout,
+ );
+ agent.link.respond(*sub, resp);
+ }
+ } else {
+ for sub in agent.subscribers.iter() {
+ let resp = Response::Error(
+ MatrixError::SDKError(e.to_string()),
+ );
+ agent.link.respond(*sub, resp);
+ }
+ }
+ }
+ }
+ } else {
+ for sub in agent.subscribers.iter() {
+ let resp = Response::Error(MatrixError::SDKError(
+ e.to_string(),
+ ));
+ agent.link.respond(*sub, resp);
}
- }
- } else {
- for sub in subscribers.iter() {
- let resp =
- Response::Error(MatrixError::SDKError(e.to_string()));
- agent.link.respond(*sub, resp);
}
}
}
+ });
+ }
+ Err(e) => {
+ for sub in self.subscribers.iter() {
+ let resp = Response::Error(e.clone());
+ self.link.respond(*sub, resp);
}
}
- });
+ }
}
Request::GetLoggedIn => {
- let login_client = self.login();
- if login_client.is_none() {
- for sub in self.subscribers.iter() {
- let resp = Response::Error(MatrixError::MissingClient);
- self.link.respond(*sub, resp);
+ let homeserver = self.matrix_state.homeserver.as_ref();
+ let session = self.session.clone();
+ let client = login(session.as_ref(), homeserver);
+ match client {
+ Ok(client) => {
+ info!("Got client");
+ self.matrix_client = Some(client);
+ info!("Client set");
+ let agent = self.clone();
+ spawn_local(async move {
+ let logged_in = agent.get_logged_in().await;
+
+ if !logged_in && session.is_some() {
+ error!("Not logged in but got session");
+ } else {
+ for sub in agent.subscribers.iter() {
+ let resp = Response::LoggedIn(logged_in);
+ agent.link.respond(*sub, resp);
+ }
+ }
+ });
}
- return;
- }
-
- // Always clone agent after having tried to login!
- let agent = self.clone();
-
- spawn_local(async move {
- let logged_in = agent.get_logged_in().await;
-
- if !logged_in && agent.session.is_some() {
- error!("Not logged in but got session");
- } else {
- for sub in agent.subscribers.iter() {
- let resp = Response::LoggedIn(logged_in);
- agent.link.respond(*sub, resp);
+ Err(e) => {
+ error!("Got no client: {:?}", e);
+ for sub in self.subscribers.iter() {
+ let resp = Response::Error(e.clone());
+ self.link.respond(*sub, resp);
}
}
- });
+ }
}
Request::StartSync => {
// Always clone agent after having tried to login!
@@ -436,64 +435,4 @@ impl MatrixAgent {
}
self.matrix_client.as_ref().unwrap().logged_in().await
}
-
- fn login(&mut self) -> Option<Client> {
- info!("preparing client");
- if self.session.is_some() {
- info!("restoring login");
- let homeserver = &self.session.as_ref().unwrap().homeserver_url;
-
- let client_config = ClientConfig::new();
- let homeserver_url = Url::parse(homeserver).unwrap();
- let client = Client::new_with_config(homeserver_url, client_config).unwrap();
- self.matrix_client = Some(client.clone());
-
- info!("got client");
- // Also directly restore Login data
- let stored_session = self.session.clone().unwrap();
- let session = Session {
- access_token: stored_session.access_token,
- user_id: matrix_sdk::identifiers::UserId::try_from(stored_session.user_id.as_str())
- .unwrap(),
- device_id: stored_session.device_id,
- };
- let client_clone = client.clone();
- info!("before restore");
- spawn_local(async move {
- info!("before inner restore");
- client_clone.restore_login(session).await;
- info!("after restore");
- });
-
- Some(client)
- } else if self.matrix_state.homeserver.is_none() {
- for sub in self.subscribers.iter() {
- let resp = Response::Error(MatrixError::MissingFields(Field::Homeserver));
- self.link.respond(*sub, resp);
- }
- None
- } else if self.matrix_state.username.is_none() {
- for sub in self.subscribers.iter() {
- let resp = Response::Error(MatrixError::MissingFields(Field::MXID));
- self.link.respond(*sub, resp);
- }
- None
- } else if self.matrix_state.password.is_none() {
- for sub in self.subscribers.iter() {
- let resp = Response::Error(MatrixError::MissingFields(Field::Password));
- self.link.respond(*sub, resp);
- }
- None
- } else {
- info!("new login");
- let homeserver = self.matrix_state.homeserver.clone().unwrap();
-
- let client_config = ClientConfig::new();
- let homeserver_url = Url::parse(&homeserver).unwrap();
- let client = Client::new_with_config(homeserver_url, client_config).unwrap();
- self.matrix_client = Some(client.clone());
-
- Some(client)
- }
- }
}
diff --git a/src/app/mod.rs b/src/app/mod.rs
@@ -2,7 +2,7 @@ use yew::{prelude::*, virtual_dom::VNode};
use yew_router::agent::RouteRequest::ChangeRoute;
use yew_router::{prelude::*, Switch};
-use crate::app::matrix::{MatrixAgent, Response, SessionStore};
+use crate::app::matrix::{login::SessionStore, MatrixAgent, Response};
use crate::app::views::{login::Login, main_view::MainView};
use crate::constants::AUTH_KEY;
use log::*;
diff --git a/src/errors.rs b/src/errors.rs
@@ -36,4 +36,9 @@ pub enum MatrixError {
/// This can't use transparent as we need Clone
#[error("An error occurred in the Matrix client library: `{0}`")]
SDKError(String),
+
+ /// An error occurred in the URL parse library.
+ /// This can't use transparent as we need Serialize, Deserialize
+ #[error("An error occurred in the URL parse library: `{0}`")]
+ UrlParseError(String),
}