Update login endpoint to r0.6.0

This commit is contained in:
Jonas Platte 2019-04-21 01:07:49 +02:00
parent b4692ec2a2
commit 01dd745a06
No known key found for this signature in database
GPG Key ID: 7D261D771D915378
4 changed files with 237 additions and 27 deletions

View File

@ -3,8 +3,6 @@
use ruma_api::ruma_api;
use serde::{Deserialize, Serialize};
use super::login::LoginType;
ruma_api! {
metadata {
description: "Gets the homeserver's supported login types to authenticate users. Clients should pick one of these and supply it as the type when logging in.",
@ -30,3 +28,15 @@ pub struct LoginFlow {
#[serde(rename = "type")]
pub login_type: LoginType,
}
/// The authentication mechanism.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum LoginType {
/// A password is supplied to authenticate.
#[serde(rename = "m.login.password")]
Password,
/// Token-based login.
#[serde(rename = "m.login.token")]
Token,
}

View File

@ -1,9 +1,10 @@
//! [POST /_matrix/client/r0/login](https://matrix.org/docs/spec/client_server/r0.4.0.html#post-matrix-client-r0-login)
//! [POST /_matrix/client/r0/login](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-login)
use crate::r0::thirdparty::Medium;
use ruma_api::ruma_api;
use ruma_identifiers::{DeviceId, UserId};
use serde::{Deserialize, Serialize};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::r0::thirdparty::Medium;
ruma_api! {
metadata {
@ -16,47 +17,182 @@ ruma_api! {
}
request {
/// The user's password.
pub password: String,
/// When logging in using a third party identifier, the medium of the identifier.
#[serde(skip_serializing_if = "Option::is_none")]
pub medium: Option<Medium>,
/// Identification information for the user.
#[serde(flatten)]
pub user: UserInfo,
/// The authentication mechanism.
#[serde(rename = "type")]
pub login_type: LoginType,
/// The fully qualified user ID or just local part of the user ID.
pub user: String,
/// Third party identifier for the user.
#[serde(skip_serializing_if = "Option::is_none")]
pub address: Option<String>,
#[serde(flatten)]
pub login_info: LoginInfo,
/// ID of the client device
#[serde(skip_serializing_if = "Option::is_none")]
pub device_id: Option<DeviceId>,
/// A display name to assign to the newly-created device. Ignored if device_id corresponds
/// to a known device.
#[serde(skip_serializing_if = "Option::is_none")]
pub initial_device_display_name: Option<String>,
}
response {
/// The fully-qualified Matrix ID that has been registered.
pub user_id: UserId,
/// An access token for the account.
pub access_token: String,
/// The hostname of the homeserver on which the account has been registered.
pub home_server: String,
/// A refresh token may be exchanged for a new access token using the /tokenrefresh API
/// endpoint.
///
/// Deprecated: Clients should extract the server_name from user_id (by splitting at the
/// first colon) if they require it.
#[serde(skip_serializing_if = "Option::is_none")]
pub refresh_token: Option<String>,
/// The fully-qualified Matrix ID that has been registered.
pub user_id: UserId,
pub home_server: Option<String>,
/// ID of the logged-in device.
///
/// Will be the same as the corresponging parameter in the request, if one was
/// specified.
pub device_id: String,
/// Client configuration provided by the server.
///
/// If present, clients SHOULD use the provided object to reconfigure themselves.
pub well_known: Option<DiscoveryInfo>,
}
}
/// Identification information for the user.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum UserInfo {
/// Either a fully qualified Matrix user ID, or just the localpart (as part of the 'identifier'
/// field, recommended since r0.4.0).
MatrixId(String),
/// Third party identifier (as part of the 'identifier' field, recommended since r0.4.0).
ThirdPartyId {
/// Third party identifier for the user.
address: String,
/// The medium of the identifier.
medium: Medium,
},
/// Same as third-party identification with medium == msisdn, but with a non-canonicalised
/// phone number.
PhoneNumber {
/// The country that the phone number is from.
country: String,
/// The phone number.
phone: String,
},
}
/// The authentication mechanism.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub enum LoginType {
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum LoginInfo {
/// A password is supplied to authenticate.
#[serde(rename = "m.login.password")]
Password,
Password {
/// The password.
password: String,
},
/// Token-based login.
#[serde(rename = "m.login.token")]
Token {
/// The token.
token: String,
},
}
/// Client configuration provided by the server.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct DiscoveryInfo {
#[serde(rename = "m.homeserver")]
homeserver: HomeserverInfo,
#[serde(rename = "m.identity_server")]
identity_server: Option<IdentityServerInfo>,
}
/// Information about the homeserver to connect to.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct HomeserverInfo {
/// The base URL for the homeserver for client-server connections.
base_url: String,
}
/// Information about the identity server to connect to.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct IdentityServerInfo {
/// The base URL for the identity server for client-server connections.
base_url: String,
}
mod user_serde;
impl Serialize for UserInfo {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
user_serde::UserInfo::from(self).serialize(serializer)
}
}
impl<'de> Deserialize<'de> for UserInfo {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
user_serde::UserInfo::deserialize(deserializer).map(Into::into)
}
}
#[cfg(test)]
mod tests {
use serde_json;
use super::{LoginInfo, UserInfo};
#[test]
fn deserialize_login_type() {
assert_eq!(
serde_json::from_str::<LoginInfo>(
r#"
{
"type": "m.login.password",
"password": "ilovebananas"
}
"#,
)
.unwrap(),
LoginInfo::Password {
password: "ilovebananas".into()
}
);
assert_eq!(
serde_json::from_str::<LoginInfo>(
r#"
{
"type": "m.login.token",
"token": "1234567890abcdef"
}
"#,
)
.unwrap(),
LoginInfo::Token {
token: "1234567890abcdef".into()
}
);
}
#[test]
fn deserialize_user() {
assert_eq!(
serde_json::from_str::<UserInfo>(
r#"
{
"identifier": {
"type": "m.id.user",
"user": "cheeky_monkey"
}
}
"#,
)
.unwrap(),
UserInfo::MatrixId("cheeky_monkey".into())
);
}
}

View File

@ -0,0 +1,64 @@
//! Helper module for the Serialize / Deserialize impl's for the User struct
//! in the parent module.
use serde::{Deserialize, Serialize};
use super::Medium;
// The following three 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, Deserialize, Serialize)]
pub struct UserInfo<'a> {
#[serde(borrow)]
identifier: UserIdentifier<'a>,
}
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(tag = "type")]
pub enum UserIdentifier<'a> {
#[serde(rename = "m.id.user")]
MatrixId { user: &'a str },
#[serde(rename = "m.id.thirdparty")]
ThirdPartyId { medium: Medium, address: &'a str },
#[serde(rename = "m.id.phone")]
PhoneNumber { country: &'a str, phone: &'a str },
}
impl<'a> From<&'a super::UserInfo> for UserInfo<'a> {
fn from(su: &'a super::UserInfo) -> Self {
use super::UserInfo::*;
match su {
MatrixId(user) => UserInfo {
identifier: UserIdentifier::MatrixId { user },
},
ThirdPartyId { address, medium } => UserInfo {
identifier: UserIdentifier::ThirdPartyId {
address,
medium: *medium,
},
},
PhoneNumber { country, phone } => UserInfo {
identifier: UserIdentifier::PhoneNumber { country, phone },
},
}
}
}
impl Into<super::UserInfo> for UserInfo<'_> {
fn into(self) -> super::UserInfo {
use super::UserInfo::*;
match self.identifier {
UserIdentifier::MatrixId { user } => MatrixId(user.to_owned()),
UserIdentifier::ThirdPartyId { address, medium } => ThirdPartyId {
address: address.to_owned(),
medium: medium.to_owned(),
},
UserIdentifier::PhoneNumber { country, phone } => PhoneNumber {
country: country.to_owned(),
phone: phone.to_owned(),
},
}
}
}

View File

@ -74,7 +74,7 @@ pub struct User {
}
/// The medium of a third party identifier.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum Medium {
/// Email address identifier