mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-18 13:40:55 -04:00
fix(bindings): Verify entered homeserver before proxy availability
The reported errors weren't that helpful to the user. Additionally attempt discovery when a URL is entered before falling back to the URL directly.
This commit is contained in:
@@ -2,7 +2,7 @@ use std::sync::{Arc, RwLock};
|
||||
|
||||
use futures_util::future::join3;
|
||||
use matrix_sdk::{
|
||||
ruma::{OwnedDeviceId, UserId},
|
||||
ruma::{IdParseError, OwnedDeviceId, UserId},
|
||||
Session,
|
||||
};
|
||||
use zeroize::Zeroize;
|
||||
@@ -28,6 +28,8 @@ impl Drop for AuthenticationService {
|
||||
pub enum AuthenticationError {
|
||||
#[error("A successful call to configure_homeserver must be made first.")]
|
||||
ClientMissing,
|
||||
#[error("{message}")]
|
||||
InvalidServerName { message: String },
|
||||
#[error("The homeserver doesn't provide a trusted a sliding sync proxy in its well-known configuration.")]
|
||||
SlidingSyncNotAvailable,
|
||||
#[error("Login was successful but is missing a valid Session to configure the file store.")]
|
||||
@@ -42,6 +44,12 @@ impl From<anyhow::Error> for AuthenticationError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IdParseError> for AuthenticationError {
|
||||
fn from(e: IdParseError) -> AuthenticationError {
|
||||
AuthenticationError::InvalidServerName { message: e.to_string() }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(uniffi::Object)]
|
||||
pub struct HomeserverLoginDetails {
|
||||
url: String,
|
||||
@@ -112,32 +120,47 @@ impl AuthenticationService {
|
||||
|
||||
/// Updates the service to authenticate with the homeserver for the
|
||||
/// specified address.
|
||||
pub fn configure_homeserver(&self, server_name: String) -> Result<(), AuthenticationError> {
|
||||
pub fn configure_homeserver(
|
||||
&self,
|
||||
server_name_or_homeserver_url: String,
|
||||
) -> Result<(), AuthenticationError> {
|
||||
let mut builder = Arc::new(ClientBuilder::new()).base_path(self.base_path.clone());
|
||||
|
||||
if server_name.starts_with("http://") || server_name.starts_with("https://") {
|
||||
builder = builder.homeserver_url(server_name)
|
||||
} else {
|
||||
builder = builder.server_name(server_name);
|
||||
}
|
||||
// Remove any URL scheme from the name to attempt discovery first.
|
||||
let server_name = matrix_sdk::sanitize_server_name(&server_name_or_homeserver_url)
|
||||
.map_err(AuthenticationError::from)?;
|
||||
|
||||
let client = builder.build().map_err(AuthenticationError::from)?;
|
||||
builder = builder.server_name(server_name.to_string());
|
||||
|
||||
// Make sure there's a sliding sync proxy available one way or another.
|
||||
let client = builder
|
||||
.build()
|
||||
.or_else(|e| {
|
||||
if !server_name_or_homeserver_url.starts_with("http://")
|
||||
&& !server_name_or_homeserver_url.starts_with("http://")
|
||||
{
|
||||
return Err(e);
|
||||
}
|
||||
// When discovery fails, fallback to the homeserver URL if supplied.
|
||||
let mut builder = Arc::new(ClientBuilder::new()).base_path(self.base_path.clone());
|
||||
builder = builder.homeserver_url(server_name_or_homeserver_url);
|
||||
builder.build()
|
||||
})
|
||||
.map_err(AuthenticationError::from)?;
|
||||
|
||||
let details = RUNTIME.block_on(async { self.details_from_client(&client).await })?;
|
||||
|
||||
// Now we've verified that it's a valid homeserver, make sure
|
||||
// there's a sliding sync proxy available one way or another.
|
||||
if self.custom_sliding_sync_proxy.read().unwrap().is_none()
|
||||
&& client.discovered_sliding_sync_proxy().is_none()
|
||||
{
|
||||
return Err(AuthenticationError::SlidingSyncNotAvailable);
|
||||
}
|
||||
|
||||
RUNTIME.block_on(async move {
|
||||
let details = Arc::new(self.details_from_client(&client).await?);
|
||||
*self.client.write().unwrap() = Some(client);
|
||||
*self.homeserver_details.write().unwrap() = Some(Arc::new(details));
|
||||
|
||||
*self.client.write().unwrap() = Some(client);
|
||||
*self.homeserver_details.write().unwrap() = Some(details);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Performs a password login using the current homeserver.
|
||||
|
||||
@@ -55,6 +55,7 @@ pub use error::ImageError;
|
||||
pub use error::{Error, HttpError, HttpResult, RefreshTokenError, Result, RumaApiError};
|
||||
pub use http_client::HttpSend;
|
||||
pub use media::Media;
|
||||
pub use ruma::{IdParseError, OwnedServerName, ServerName};
|
||||
#[cfg(feature = "experimental-sliding-sync")]
|
||||
pub use sliding_sync::{
|
||||
RoomListEntry, SlidingSync, SlidingSyncBuilder, SlidingSyncMode, SlidingSyncRoom,
|
||||
@@ -73,3 +74,9 @@ fn init_logging() {
|
||||
.with(tracing_subscriber::fmt::layer().with_test_writer())
|
||||
.init();
|
||||
}
|
||||
|
||||
/// Creates a server name from a user supplied string. The string is first
|
||||
/// sanitized by removing the http(s) scheme before being parsed.
|
||||
pub fn sanitize_server_name(s: &str) -> Result<OwnedServerName, IdParseError> {
|
||||
ServerName::parse(s.trim_start_matches("http://").trim_start_matches("https://"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user