Update login endpoint to r0.6.0
This commit is contained in:
parent
b4692ec2a2
commit
01dd745a06
@ -3,8 +3,6 @@
|
|||||||
use ruma_api::ruma_api;
|
use ruma_api::ruma_api;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::login::LoginType;
|
|
||||||
|
|
||||||
ruma_api! {
|
ruma_api! {
|
||||||
metadata {
|
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.",
|
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")]
|
#[serde(rename = "type")]
|
||||||
pub login_type: LoginType,
|
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,
|
||||||
|
}
|
||||||
|
@ -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_api::ruma_api;
|
||||||
use ruma_identifiers::{DeviceId, UserId};
|
use ruma_identifiers::{DeviceId, UserId};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
|
||||||
|
use crate::r0::thirdparty::Medium;
|
||||||
|
|
||||||
ruma_api! {
|
ruma_api! {
|
||||||
metadata {
|
metadata {
|
||||||
@ -16,47 +17,182 @@ ruma_api! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
request {
|
request {
|
||||||
/// The user's password.
|
/// Identification information for the user.
|
||||||
pub password: String,
|
#[serde(flatten)]
|
||||||
/// When logging in using a third party identifier, the medium of the identifier.
|
pub user: UserInfo,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
|
||||||
pub medium: Option<Medium>,
|
|
||||||
/// The authentication mechanism.
|
/// The authentication mechanism.
|
||||||
#[serde(rename = "type")]
|
#[serde(flatten)]
|
||||||
pub login_type: LoginType,
|
pub login_info: LoginInfo,
|
||||||
/// 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>,
|
|
||||||
/// ID of the client device
|
/// ID of the client device
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub device_id: Option<DeviceId>,
|
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 {
|
response {
|
||||||
|
/// The fully-qualified Matrix ID that has been registered.
|
||||||
|
pub user_id: UserId,
|
||||||
/// An access token for the account.
|
/// An access token for the account.
|
||||||
pub access_token: String,
|
pub access_token: String,
|
||||||
/// The hostname of the homeserver on which the account has been registered.
|
/// 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
|
/// Deprecated: Clients should extract the server_name from user_id (by splitting at the
|
||||||
/// endpoint.
|
/// first colon) if they require it.
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub refresh_token: Option<String>,
|
pub home_server: Option<String>,
|
||||||
/// The fully-qualified Matrix ID that has been registered.
|
|
||||||
pub user_id: UserId,
|
|
||||||
/// ID of the logged-in device.
|
/// ID of the logged-in device.
|
||||||
///
|
///
|
||||||
/// Will be the same as the corresponging parameter in the request, if one was
|
/// Will be the same as the corresponging parameter in the request, if one was
|
||||||
/// specified.
|
/// specified.
|
||||||
pub device_id: String,
|
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.
|
/// The authentication mechanism.
|
||||||
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||||
pub enum LoginType {
|
#[serde(tag = "type")]
|
||||||
|
pub enum LoginInfo {
|
||||||
/// A password is supplied to authenticate.
|
/// A password is supplied to authenticate.
|
||||||
#[serde(rename = "m.login.password")]
|
#[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())
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
64
src/r0/session/login/user_serde.rs
Normal file
64
src/r0/session/login/user_serde.rs
Normal 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(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -74,7 +74,7 @@ pub struct User {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The medium of a third party identifier.
|
/// 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")]
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum Medium {
|
pub enum Medium {
|
||||||
/// Email address identifier
|
/// Email address identifier
|
||||||
|
Loading…
x
Reference in New Issue
Block a user