client-api: Support custom login types
This commit is contained in:
parent
0c8adbb69e
commit
341869c83c
@ -1,7 +1,7 @@
|
||||
//! [GET /_matrix/client/r0/login](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-login)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use ruma_serde::StringEnum;
|
||||
|
||||
ruma_api! {
|
||||
metadata: {
|
||||
@ -18,7 +18,8 @@ ruma_api! {
|
||||
|
||||
response: {
|
||||
/// The homeserver's supported login types.
|
||||
pub flows: Vec<LoginType>
|
||||
#[serde(with = "login_type_list_serde")]
|
||||
pub flows: Vec<LoginType>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
@ -39,33 +40,51 @@ impl Response {
|
||||
}
|
||||
|
||||
/// An authentication mechanism.
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
|
||||
#[serde(tag = "type")]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
|
||||
pub enum LoginType {
|
||||
/// A password is supplied to authenticate.
|
||||
#[serde(rename = "m.login.password")]
|
||||
#[ruma_enum(rename = "m.login.password")]
|
||||
Password,
|
||||
|
||||
/// Token-based login.
|
||||
#[serde(rename = "m.login.token")]
|
||||
#[ruma_enum(rename = "m.login.token")]
|
||||
Token,
|
||||
|
||||
/// SSO-based login.
|
||||
#[serde(rename = "m.login.sso")]
|
||||
#[ruma_enum(rename = "m.login.sso")]
|
||||
Sso,
|
||||
|
||||
#[doc(hidden)]
|
||||
_Custom(String),
|
||||
}
|
||||
|
||||
mod login_type_list_serde;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use matches::assert_matches;
|
||||
use serde::Deserialize;
|
||||
use serde_json::{from_value as from_json_value, json};
|
||||
|
||||
use super::LoginType;
|
||||
use super::{login_type_list_serde, LoginType};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Foo {
|
||||
#[serde(with = "login_type_list_serde")]
|
||||
pub flows: Vec<LoginType>,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deserialize_login_type() {
|
||||
assert_eq!(
|
||||
from_json_value::<LoginType>(json!({ "type": "m.login.password" })).unwrap(),
|
||||
LoginType::Password,
|
||||
assert_matches!(
|
||||
from_json_value::<Foo>(json!({
|
||||
"flows": [
|
||||
{ "type": "m.login.password" }
|
||||
],
|
||||
})),
|
||||
Ok(Foo { flows })
|
||||
if flows.len() == 1
|
||||
&& flows[0] == LoginType::Password
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,31 @@
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use super::LoginType;
|
||||
|
||||
pub fn serialize<S>(login_types: &[LoginType], serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
#[derive(Serialize)]
|
||||
struct Wrap<'a> {
|
||||
#[serde(rename = "type")]
|
||||
inner: &'a LoginType,
|
||||
}
|
||||
|
||||
serializer.collect_seq(login_types.iter().map(|ty| Wrap { inner: ty }))
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<LoginType>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
struct Wrap {
|
||||
#[serde(rename = "type")]
|
||||
inner: LoginType,
|
||||
}
|
||||
|
||||
// Could be optimized by using a visitor, but that's a bunch of extra code
|
||||
let vec = Vec::<Wrap>::deserialize(deserializer)?;
|
||||
Ok(vec.into_iter().map(|w| w.inner).collect())
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user