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`
* Switch from `AnyEvent` to `AnyRoomEvent` in `r0::search::search_events`
* 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:

View File

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

View File

@ -5,13 +5,8 @@ use ruma_common::thirdparty::Medium;
use ruma_serde::Outgoing;
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.
#[derive(Clone, Debug, PartialEq, Eq, Outgoing, Serialize)]
pub(crate) struct UserInfo<'a> {
pub identifier: UserIdentifier<'a>,
}
#[derive(Clone, Debug, PartialEq, Eq, Outgoing, Serialize)]
#[serde(tag = "type")]
pub(crate) enum UserIdentifier<'a> {
@ -23,32 +18,28 @@ pub(crate) enum UserIdentifier<'a> {
PhoneNumber { country: &'a str, phone: &'a str },
}
impl<'a> From<super::UserInfo<'a>> for UserInfo<'a> {
fn from(info: super::UserInfo<'a>) -> Self {
use super::UserInfo as Info;
use UserIdentifier as Id;
impl<'a> From<super::UserIdentifier<'a>> for UserIdentifier<'a> {
fn from(id: super::UserIdentifier<'a>) -> Self {
use super::UserIdentifier as SuperId;
use UserIdentifier as SerdeId;
match info {
Info::MatrixId(user) => UserInfo { identifier: Id::MatrixId { user } },
Info::ThirdPartyId { address, medium } => {
UserInfo { identifier: Id::ThirdPartyId { address, medium } }
}
Info::PhoneNumber { country, phone } => {
UserInfo { identifier: Id::PhoneNumber { country, phone } }
}
match id {
SuperId::MatrixId(user) => SerdeId::MatrixId { user },
SuperId::ThirdPartyId { address, medium } => SerdeId::ThirdPartyId { address, medium },
SuperId::PhoneNumber { country, phone } => SerdeId::PhoneNumber { country, phone },
}
}
}
impl From<IncomingUserInfo> for super::IncomingUserInfo {
fn from(info: IncomingUserInfo) -> super::IncomingUserInfo {
use super::IncomingUserInfo as Info;
use IncomingUserIdentifier as Id;
impl From<IncomingUserIdentifier> for super::IncomingUserIdentifier {
fn from(id: IncomingUserIdentifier) -> super::IncomingUserIdentifier {
use super::IncomingUserIdentifier as SuperId;
use IncomingUserIdentifier as SerdeId;
match info.identifier {
Id::MatrixId { user } => Info::MatrixId(user),
Id::ThirdPartyId { address, medium } => Info::ThirdPartyId { address, medium },
Id::PhoneNumber { country, phone } => Info::PhoneNumber { country, phone },
match id {
SerdeId::MatrixId { user } => SuperId::MatrixId(user),
SerdeId::ThirdPartyId { address, medium } => SuperId::ThirdPartyId { address, medium },
SerdeId::PhoneNumber { country, phone } => SuperId::PhoneNumber { country, phone },
}
}
}

View File

@ -214,11 +214,13 @@ impl Client {
device_id: Option<&DeviceId>,
initial_device_display_name: Option<&str>,
) -> 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
.request(assign!(
LoginRequest::new(UserInfo::MatrixId(user), LoginInfo::Password { password }), {
LoginRequest::new(LoginInfo::Password { identifier: UserIdentifier::MatrixId(user), password }), {
device_id,
initial_device_display_name,
}