client-api: Move user in login::Request to identifier in login::LoginInfo::Password

This commit is contained in:
Kévin Commaille 2021-03-15 10:36:54 +01:00 committed by GitHub
parent 684468bc5d
commit 02e6c935b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 71 additions and 50 deletions

View File

@ -62,6 +62,9 @@ Breaking changes:
* `error::ErrorKind` no longer implements `Copy`, `FromStr` * `error::ErrorKind` no longer implements `Copy`, `FromStr`
* Switch from `AnyEvent` to `AnyRoomEvent` in `r0::search::search_events` * Switch from `AnyEvent` to `AnyRoomEvent` in `r0::search::search_events`
* Move `r0::account::request_openid_token::TokenType` to `ruma-common` crate * Move `r0::account::request_openid_token::TokenType` to `ruma-common` crate
* Move `user: UserInfo` in `r0::session::login::Request` to `identifier: UserIdentifier` in
`r0::session::login::LoginInfo::Password`
* `r0::session::login::Request::new` takes only `login_info: LoginInfo` as a param
Improvements: Improvements:

View File

@ -17,10 +17,6 @@ ruma_api! {
} }
request: { request: {
/// Identification information for the user.
#[serde(flatten)]
pub user: UserInfo<'a>,
/// The authentication mechanism. /// The authentication mechanism.
#[serde(flatten)] #[serde(flatten)]
pub login_info: LoginInfo<'a>, pub login_info: LoginInfo<'a>,
@ -65,9 +61,9 @@ ruma_api! {
} }
impl<'a> Request<'a> { impl<'a> Request<'a> {
/// Creates a new `Request` with the given user and login info. /// Creates a new `Request` with the given login info.
pub fn new(user: UserInfo<'a>, login_info: LoginInfo<'a>) -> Self { pub fn new(login_info: LoginInfo<'a>) -> Self {
Self { user, login_info, device_id: None, initial_device_display_name: None } Self { login_info, device_id: None, initial_device_display_name: None }
} }
} }
@ -80,8 +76,8 @@ impl Response {
/// Identification information for the user. /// Identification information for the user.
#[derive(Clone, Debug, PartialEq, Eq, Outgoing, Serialize)] #[derive(Clone, Debug, PartialEq, Eq, Outgoing, Serialize)]
#[serde(from = "user_serde::IncomingUserInfo", into = "user_serde::UserInfo")] #[serde(from = "user_serde::IncomingUserIdentifier", into = "user_serde::UserIdentifier")]
pub enum UserInfo<'a> { pub enum UserIdentifier<'a> {
/// Either a fully qualified Matrix user ID, or just the localpart (as part of the 'identifier' /// Either a fully qualified Matrix user ID, or just the localpart (as part of the 'identifier'
/// field). /// field).
MatrixId(&'a str), MatrixId(&'a str),
@ -110,9 +106,11 @@ pub enum UserInfo<'a> {
#[derive(Clone, Debug, PartialEq, Eq, Outgoing, Serialize)] #[derive(Clone, Debug, PartialEq, Eq, Outgoing, Serialize)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub enum LoginInfo<'a> { pub enum LoginInfo<'a> {
/// A password is supplied to authenticate. /// An identifier and password are supplied to authenticate.
#[serde(rename = "m.login.password")] #[serde(rename = "m.login.password")]
Password { Password {
/// Identification information for the user.
identifier: UserIdentifier<'a>,
/// The password. /// The password.
password: &'a str, password: &'a str,
}, },
@ -159,18 +157,24 @@ mod tests {
use ruma_api::OutgoingRequest; use ruma_api::OutgoingRequest;
use serde_json::{from_value as from_json_value, json, Value as JsonValue}; use serde_json::{from_value as from_json_value, json, Value as JsonValue};
use super::{IncomingLoginInfo, IncomingUserInfo, LoginInfo, Medium, Request, UserInfo}; use super::{
IncomingLoginInfo, IncomingUserIdentifier, LoginInfo, Medium, Request, UserIdentifier,
};
#[test] #[test]
fn deserialize_login_type() { fn deserialize_login_type() {
assert_matches!( assert_matches!(
from_json_value(json!({ from_json_value(json!({
"type": "m.login.password", "type": "m.login.password",
"identifier": {
"type": "m.id.user",
"user": "cheeky_monkey"
},
"password": "ilovebananas" "password": "ilovebananas"
})) }))
.unwrap(), .unwrap(),
IncomingLoginInfo::Password { password } IncomingLoginInfo::Password { identifier: IncomingUserIdentifier::MatrixId(user), password }
if password == "ilovebananas" if user == "cheeky_monkey" && password == "ilovebananas"
); );
assert_matches!( assert_matches!(
@ -188,13 +192,11 @@ mod tests {
fn deserialize_user() { fn deserialize_user() {
assert_matches!( assert_matches!(
from_json_value(json!({ from_json_value(json!({
"identifier": {
"type": "m.id.user", "type": "m.id.user",
"user": "cheeky_monkey" "user": "cheeky_monkey"
}
})) }))
.unwrap(), .unwrap(),
IncomingUserInfo::MatrixId(id) IncomingUserIdentifier::MatrixId(id)
if id == "cheeky_monkey" if id == "cheeky_monkey"
); );
} }
@ -202,7 +204,6 @@ mod tests {
#[test] #[test]
fn serialize_login_request_body() { fn serialize_login_request_body() {
let req: http::Request<Vec<u8>> = Request { let req: http::Request<Vec<u8>> = Request {
user: UserInfo::ThirdPartyId { address: "hello@example.com", medium: Medium::Email },
login_info: LoginInfo::Token { token: "0xdeadbeef" }, login_info: LoginInfo::Token { token: "0xdeadbeef" },
device_id: None, device_id: None,
initial_device_display_name: Some("test"), initial_device_display_name: Some("test"),
@ -210,6 +211,30 @@ mod tests {
.try_into_http_request("https://homeserver.tld", None) .try_into_http_request("https://homeserver.tld", None)
.unwrap(); .unwrap();
let req_body_value: JsonValue = serde_json::from_slice(req.body()).unwrap();
assert_eq!(
req_body_value,
json!({
"type": "m.login.token",
"token": "0xdeadbeef",
"initial_device_display_name": "test",
})
);
let req: http::Request<Vec<u8>> = Request {
login_info: LoginInfo::Password {
identifier: UserIdentifier::ThirdPartyId {
address: "hello@example.com",
medium: Medium::Email,
},
password: "deadbeef",
},
device_id: None,
initial_device_display_name: Some("test"),
}
.try_into_http_request("https://homeserver.tld", None)
.unwrap();
let req_body_value: JsonValue = serde_json::from_slice(req.body()).unwrap(); let req_body_value: JsonValue = serde_json::from_slice(req.body()).unwrap();
assert_eq!( assert_eq!(
req_body_value, req_body_value,
@ -219,10 +244,10 @@ mod tests {
"medium": "email", "medium": "email",
"address": "hello@example.com" "address": "hello@example.com"
}, },
"type": "m.login.token", "type": "m.login.password",
"token": "0xdeadbeef", "password": "deadbeef",
"initial_device_display_name": "test", "initial_device_display_name": "test",
}) })
) );
} }
} }

View File

@ -5,13 +5,8 @@ use ruma_common::thirdparty::Medium;
use ruma_serde::Outgoing; use ruma_serde::Outgoing;
use serde::Serialize; use serde::Serialize;
// The following three structs could just be used in place of the one in the parent module, but // The following structs could just be used in place of the one in the parent module, but
// that one is arguably much easier to deal with. // that one is arguably much easier to deal with.
#[derive(Clone, Debug, PartialEq, Eq, Outgoing, Serialize)]
pub(crate) struct UserInfo<'a> {
pub identifier: UserIdentifier<'a>,
}
#[derive(Clone, Debug, PartialEq, Eq, Outgoing, Serialize)] #[derive(Clone, Debug, PartialEq, Eq, Outgoing, Serialize)]
#[serde(tag = "type")] #[serde(tag = "type")]
pub(crate) enum UserIdentifier<'a> { pub(crate) enum UserIdentifier<'a> {
@ -23,32 +18,28 @@ pub(crate) enum UserIdentifier<'a> {
PhoneNumber { country: &'a str, phone: &'a str }, PhoneNumber { country: &'a str, phone: &'a str },
} }
impl<'a> From<super::UserInfo<'a>> for UserInfo<'a> { impl<'a> From<super::UserIdentifier<'a>> for UserIdentifier<'a> {
fn from(info: super::UserInfo<'a>) -> Self { fn from(id: super::UserIdentifier<'a>) -> Self {
use super::UserInfo as Info; use super::UserIdentifier as SuperId;
use UserIdentifier as Id; use UserIdentifier as SerdeId;
match info { match id {
Info::MatrixId(user) => UserInfo { identifier: Id::MatrixId { user } }, SuperId::MatrixId(user) => SerdeId::MatrixId { user },
Info::ThirdPartyId { address, medium } => { SuperId::ThirdPartyId { address, medium } => SerdeId::ThirdPartyId { address, medium },
UserInfo { identifier: Id::ThirdPartyId { address, medium } } SuperId::PhoneNumber { country, phone } => SerdeId::PhoneNumber { country, phone },
}
Info::PhoneNumber { country, phone } => {
UserInfo { identifier: Id::PhoneNumber { country, phone } }
}
} }
} }
} }
impl From<IncomingUserInfo> for super::IncomingUserInfo { impl From<IncomingUserIdentifier> for super::IncomingUserIdentifier {
fn from(info: IncomingUserInfo) -> super::IncomingUserInfo { fn from(id: IncomingUserIdentifier) -> super::IncomingUserIdentifier {
use super::IncomingUserInfo as Info; use super::IncomingUserIdentifier as SuperId;
use IncomingUserIdentifier as Id; use IncomingUserIdentifier as SerdeId;
match info.identifier { match id {
Id::MatrixId { user } => Info::MatrixId(user), SerdeId::MatrixId { user } => SuperId::MatrixId(user),
Id::ThirdPartyId { address, medium } => Info::ThirdPartyId { address, medium }, SerdeId::ThirdPartyId { address, medium } => SuperId::ThirdPartyId { address, medium },
Id::PhoneNumber { country, phone } => Info::PhoneNumber { country, phone }, SerdeId::PhoneNumber { country, phone } => SuperId::PhoneNumber { country, phone },
} }
} }
} }

View File

@ -214,11 +214,13 @@ impl Client {
device_id: Option<&DeviceId>, device_id: Option<&DeviceId>,
initial_device_display_name: Option<&str>, initial_device_display_name: Option<&str>,
) -> Result<Session, Error<ruma_client_api::Error>> { ) -> Result<Session, Error<ruma_client_api::Error>> {
use ruma_client_api::r0::session::login::{LoginInfo, Request as LoginRequest, UserInfo}; use ruma_client_api::r0::session::login::{
LoginInfo, Request as LoginRequest, UserIdentifier,
};
let response = self let response = self
.request(assign!( .request(assign!(
LoginRequest::new(UserInfo::MatrixId(user), LoginInfo::Password { password }), { LoginRequest::new(LoginInfo::Password { identifier: UserIdentifier::MatrixId(user), password }), {
device_id, device_id,
initial_device_display_name, initial_device_display_name,
} }