async_client: add docs/test for register_user, send_uiaa and RegistrationBuilder
parent
5abac19b72
commit
6df1f12b45
|
@ -17,6 +17,7 @@
|
|||
use std::collections::BTreeMap;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::fmt::{self, Debug};
|
||||
use std::path::Path;
|
||||
use std::result::Result as StdResult;
|
||||
use std::sync::Arc;
|
||||
|
@ -66,8 +67,8 @@ pub struct Client {
|
|||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
impl std::fmt::Debug for Client {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> StdResult<(), std::fmt::Error> {
|
||||
impl Debug for Client {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> StdResult<(), fmt::Error> {
|
||||
write!(fmt, "Client {{ homeserver: {} }}", self.homeserver)
|
||||
}
|
||||
}
|
||||
|
@ -106,8 +107,8 @@ pub struct ClientConfig {
|
|||
}
|
||||
|
||||
#[cfg_attr(tarpaulin, skip)]
|
||||
impl std::fmt::Debug for ClientConfig {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> StdResult<(), std::fmt::Error> {
|
||||
impl Debug for ClientConfig {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut res = fmt.debug_struct("ClientConfig");
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
|
@ -264,6 +265,7 @@ use api::r0::sync::sync_events;
|
|||
#[cfg(feature = "encryption")]
|
||||
use api::r0::to_device::send_event_to_device;
|
||||
use api::r0::typing::create_typing_event;
|
||||
use api::r0::uiaa::UiaaResponse;
|
||||
|
||||
impl Client {
|
||||
/// Creates a new client for making HTTP requests to the given homeserver.
|
||||
|
@ -414,7 +416,7 @@ impl Client {
|
|||
/// device_id from a previous login call. Note that this should be done
|
||||
/// only if the client also holds the encryption keys for this device.
|
||||
#[instrument(skip(password))]
|
||||
pub async fn login<S: Into<String> + std::fmt::Debug>(
|
||||
pub async fn login<S: Into<String> + Debug>(
|
||||
&self,
|
||||
user: S,
|
||||
password: S,
|
||||
|
@ -454,9 +456,24 @@ impl Client {
|
|||
///
|
||||
/// * `registration` - The easiest way to create this request is using the `RegistrationBuilder`.
|
||||
///
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
///
|
||||
/// # use std::convert::TryFrom;
|
||||
/// # use matrix_sdk::{Client, RegistrationBuilder};
|
||||
/// # use matrix_sdk::api::r0::account::register::RegistrationKind;
|
||||
/// # use matrix_sdk::identifiers::DeviceId;
|
||||
/// # use url::Url;
|
||||
/// # let homeserver = Url::parse("http://example.com").unwrap();
|
||||
/// # let mut rt = tokio::runtime::Runtime::new().unwrap();
|
||||
/// # rt.block_on(async {
|
||||
/// let mut builder = RegistrationBuilder::default();
|
||||
/// builder.password("pass")
|
||||
/// .username("user")
|
||||
/// .kind(RegistrationKind::User);
|
||||
/// let mut client = Client::new(homeserver).unwrap();
|
||||
/// client.register_user(builder).await;
|
||||
/// # })
|
||||
/// ```
|
||||
#[instrument(skip(registration))]
|
||||
pub async fn register_user<R: Into<register::Request>>(
|
||||
|
@ -466,7 +483,7 @@ impl Client {
|
|||
info!("Registering to {}", self.homeserver);
|
||||
|
||||
let request = registration.into();
|
||||
|
||||
println!("{:#?}", request);
|
||||
self.send_uiaa(request).await
|
||||
}
|
||||
|
||||
|
@ -896,7 +913,7 @@ impl Client {
|
|||
Ok(response)
|
||||
}
|
||||
|
||||
/// Send an arbitrary request to the server, without updating client state
|
||||
/// Send an arbitrary request to the server, without updating client state.
|
||||
///
|
||||
/// **Warning:** Because this method *does not* update the client state, it is
|
||||
/// important to make sure than you account for this yourself, and use wrapper methods
|
||||
|
@ -934,7 +951,7 @@ impl Client {
|
|||
/// // returned
|
||||
/// # })
|
||||
/// ```
|
||||
pub async fn send<Request: Endpoint<ResponseError = crate::api::Error> + std::fmt::Debug>(
|
||||
pub async fn send<Request: Endpoint<ResponseError = crate::api::Error> + Debug>(
|
||||
&self,
|
||||
request: Request,
|
||||
) -> Result<Request::Response> {
|
||||
|
@ -999,9 +1016,43 @@ impl Client {
|
|||
Ok(<Request::Response>::try_from(http_response)?)
|
||||
}
|
||||
|
||||
async fn send_uiaa<
|
||||
Request: Endpoint<ResponseError = api::r0::uiaa::UiaaResponse> + std::fmt::Debug,
|
||||
>(
|
||||
// TODO I couldn't figure out a way to share code between these two send methods
|
||||
// as they are essentially completely different types?
|
||||
//
|
||||
/// Send an arbitrary request to the server, without updating client state.
|
||||
///
|
||||
/// This version allows the client to make registration requests.
|
||||
///
|
||||
/// **Warning:** Because this method *does not* update the client state, it is
|
||||
/// important to make sure than you account for this yourself, and use wrapper methods
|
||||
/// where available. This method should *only* be used if a wrapper method for the
|
||||
/// endpoint you'd like to use is not available.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `request` - This version of send is for dealing with types that return
|
||||
/// a `UiaaResponse` as the `Endpoint<ResponseError = UiaaResponse>` associated type.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```
|
||||
/// # use std::convert::TryFrom;
|
||||
/// # use matrix_sdk::{Client, RegistrationBuilder};
|
||||
/// # use matrix_sdk::api::r0::account::register::{RegistrationKind, Request};
|
||||
/// # use matrix_sdk::identifiers::DeviceId;
|
||||
/// # use url::Url;
|
||||
/// # let homeserver = Url::parse("http://example.com").unwrap();
|
||||
/// # let mut rt = tokio::runtime::Runtime::new().unwrap();
|
||||
/// # rt.block_on(async {
|
||||
/// let mut builder = RegistrationBuilder::default();
|
||||
/// builder.password("pass")
|
||||
/// .username("user")
|
||||
/// .kind(RegistrationKind::User);
|
||||
/// let mut client = Client::new(homeserver).unwrap();
|
||||
/// let req: Request = builder.into();
|
||||
/// client.send_uiaa(req).await;
|
||||
/// # })
|
||||
/// ```
|
||||
pub async fn send_uiaa<Request: Endpoint<ResponseError = UiaaResponse> + Debug>(
|
||||
&self,
|
||||
request: Request,
|
||||
) -> Result<Request::Response> {
|
||||
|
@ -1363,14 +1414,16 @@ impl Client {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::{
|
||||
ban_user, create_receipt, create_typing_event, forget_room, invite_user, kick_user,
|
||||
leave_room, set_read_marker, Invite3pid, MessageEventContent,
|
||||
api::r0::uiaa::AuthData, ban_user, create_receipt, create_typing_event, forget_room,
|
||||
invite_user, kick_user, leave_room, register::RegistrationKind, set_read_marker,
|
||||
Invite3pid, MessageEventContent,
|
||||
};
|
||||
use super::{Client, ClientConfig, Session, SyncSettings, Url};
|
||||
use crate::events::collections::all::RoomEvent;
|
||||
use crate::events::room::member::MembershipState;
|
||||
use crate::events::room::message::TextMessageEventContent;
|
||||
use crate::identifiers::{EventId, RoomId, RoomIdOrAliasId, UserId};
|
||||
use crate::RegistrationBuilder;
|
||||
|
||||
use matrix_sdk_base::JsonStore;
|
||||
use matrix_sdk_test::{EventBuilder, EventsFile};
|
||||
|
@ -1551,6 +1604,44 @@ mod test {
|
|||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn register_error() {
|
||||
let homeserver = Url::from_str(&mockito::server_url()).unwrap();
|
||||
|
||||
let _m = mock("POST", "/_matrix/client/r0/register")
|
||||
.with_status(403)
|
||||
.with_body_from_file("../test_data/registration_response_error.json")
|
||||
.create();
|
||||
|
||||
let mut user = RegistrationBuilder::default();
|
||||
|
||||
user.username("user")
|
||||
.password("password")
|
||||
.auth(AuthData::FallbackAcknowledgement {
|
||||
session: "foobar".to_string(),
|
||||
})
|
||||
.kind(RegistrationKind::User);
|
||||
|
||||
let client = Client::new(homeserver).unwrap();
|
||||
|
||||
if let Err(err) = client.register_user(user).await {
|
||||
if let crate::Error::UiaaError(crate::FromHttpResponseError::Http(
|
||||
// TODO this should be a UiaaError need to investigate
|
||||
crate::ServerError::Unknown(e),
|
||||
)) = err
|
||||
{
|
||||
assert!(e.to_string().starts_with("EOF while parsing"))
|
||||
} else {
|
||||
panic!(
|
||||
"found the wrong `Error` type {:#?}, expected `ServerError::Unknown",
|
||||
err
|
||||
);
|
||||
}
|
||||
} else {
|
||||
panic!("this request should return an `Err` variant")
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn join_room_by_id() {
|
||||
let homeserver = Url::from_str(&mockito::server_url()).unwrap();
|
||||
|
|
|
@ -51,12 +51,16 @@ pub enum Error {
|
|||
#[error("can't convert between ruma_client_api and hyper types.")]
|
||||
IntoHttp(RumaIntoHttpError),
|
||||
|
||||
/// An error occured in the Matrix client library.
|
||||
/// An error occurred in the Matrix client library.
|
||||
#[error(transparent)]
|
||||
MatrixError(#[from] MatrixError),
|
||||
|
||||
/// An error occured in the Matrix client library.
|
||||
#[error("can't convert between ruma_client_api and hyper types.")]
|
||||
/// An error occurred while authenticating.
|
||||
///
|
||||
/// When registering or authenticating the Matrix server can send a `UiaaResponse`
|
||||
/// as the error type, this is a User-Interactive Authentication API response. This
|
||||
/// represents an error with information about how to authenticate the user.
|
||||
#[error("User-Interactive Authentication required.")]
|
||||
UiaaError(RumaResponseError<UiaaError>),
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ use crate::api;
|
|||
use crate::events::room::power_levels::PowerLevelsEventContent;
|
||||
use crate::events::EventJson;
|
||||
use crate::identifiers::{DeviceId, RoomId, UserId};
|
||||
use api::r0::account::register;
|
||||
use api::r0::account::register::RegistrationKind;
|
||||
use api::r0::filter::RoomEventFilter;
|
||||
use api::r0::membership::Invite3pid;
|
||||
|
@ -296,18 +297,16 @@ impl Into<get_message_events::Request> for MessagesRequestBuilder {
|
|||
/// ```
|
||||
/// # use std::convert::TryFrom;
|
||||
/// # use matrix_sdk::{Client, RegistrationBuilder};
|
||||
/// # use api::r0::account::register::RegistrationKind;
|
||||
/// # use matrix_sdk::api::r0::account::register::RegistrationKind;
|
||||
/// # use matrix_sdk::identifiers::DeviceId;
|
||||
/// # use url::Url;
|
||||
/// # let homeserver = Url::parse("http://example.com").unwrap();
|
||||
/// # let mut rt = tokio::runtime::Runtime::new().unwrap();
|
||||
/// # rt.block_on(async {
|
||||
/// let mut builder = RegistrationBuilder::default();
|
||||
/// builder.creation_content(false)
|
||||
/// .initial_state(vec![])
|
||||
/// .visibility(Visibility::Public)
|
||||
/// .name("name")
|
||||
/// .room_version("v1.0");
|
||||
/// builder.password("pass")
|
||||
/// .username("user")
|
||||
/// .kind(RegistrationKind::User);
|
||||
/// let mut client = Client::new(homeserver).unwrap();
|
||||
/// client.register_user(builder).await;
|
||||
/// # })
|
||||
|
@ -343,8 +342,8 @@ impl RegistrationBuilder {
|
|||
/// local part of the desired Matrix ID.
|
||||
///
|
||||
/// If omitted, the homeserver MUST generate a Matrix ID local part.
|
||||
pub fn username(&mut self, username: String) -> &mut Self {
|
||||
self.username = Some(username);
|
||||
pub fn username(&mut self, username: &str) -> &mut Self {
|
||||
self.username = Some(username.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -352,8 +351,8 @@ impl RegistrationBuilder {
|
|||
///
|
||||
/// If this does not correspond to a known client device, a new device will be created.
|
||||
/// The server will auto-generate a device_id if this is not specified.
|
||||
pub fn device_id(&mut self, device_id: String) -> &mut Self {
|
||||
self.device_id = Some(device_id);
|
||||
pub fn device_id(&mut self, device_id: &str) -> &mut Self {
|
||||
self.device_id = Some(device_id.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
|
@ -392,6 +391,20 @@ impl RegistrationBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
impl Into<register::Request> for RegistrationBuilder {
|
||||
fn into(self) -> register::Request {
|
||||
register::Request {
|
||||
password: self.password,
|
||||
username: self.username,
|
||||
device_id: self.device_id,
|
||||
initial_device_display_name: self.initial_device_display_name,
|
||||
auth: self.auth,
|
||||
kind: self.kind,
|
||||
inhibit_login: self.inhibit_login,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::collections::BTreeMap;
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"errcode": "M_FORBIDDEN",
|
||||
"error": "Invalid password",
|
||||
"completed": ["example.type.foo"],
|
||||
"flows": [
|
||||
{
|
||||
"stages": ["example.type.foo", "example.type.bar"]
|
||||
},
|
||||
{
|
||||
"stages": ["example.type.foo", "example.type.baz"]
|
||||
}
|
||||
],
|
||||
"params": {
|
||||
"example.type.baz": {
|
||||
"example_key": "foobar"
|
||||
}
|
||||
},
|
||||
"session": "xxxxxx"
|
||||
}
|
Loading…
Reference in New Issue