221 lines
6.6 KiB
Rust

#![cfg(any(feature = "client", feature = "server"))]
use assert_matches2::assert_matches;
use assign::assign;
use ruma_client_api::{
error::ErrorKind,
uiaa::{self, AuthData, AuthFlow, AuthType, UiaaInfo, UiaaResponse, UserIdentifier},
};
use ruma_common::api::{EndpointError, OutgoingResponse};
use serde_json::{
from_slice as from_json_slice, from_str as from_json_str, from_value as from_json_value, json,
to_value as to_json_value, value::to_raw_value as to_raw_json_value, Value as JsonValue,
};
#[test]
fn deserialize_user_identifier() {
assert_matches!(
from_json_value(json!({
"type": "m.id.user",
"user": "cheeky_monkey"
}))
.unwrap(),
UserIdentifier::UserIdOrLocalpart(id)
);
assert_eq!(id, "cheeky_monkey");
}
#[test]
fn serialize_auth_data_registration_token() {
let auth_data =
AuthData::RegistrationToken(assign!(uiaa::RegistrationToken::new("mytoken".to_owned()), {
session: Some("session".to_owned()),
}));
assert_eq!(
to_json_value(auth_data).unwrap(),
json!({
"type": "m.login.registration_token",
"token": "mytoken",
"session": "session",
})
);
}
#[test]
fn deserialize_auth_data_registration_token() {
let json = json!({
"type": "m.login.registration_token",
"token": "mytoken",
"session": "session",
});
assert_matches!(from_json_value(json), Ok(AuthData::RegistrationToken(data)));
assert_eq!(data.token, "mytoken");
assert_eq!(data.session.as_deref(), Some("session"));
}
#[test]
fn serialize_auth_data_fallback() {
let auth_data =
AuthData::FallbackAcknowledgement(uiaa::FallbackAcknowledgement::new("ZXY000".to_owned()));
assert_eq!(json!({ "session": "ZXY000" }), to_json_value(auth_data).unwrap());
}
#[test]
fn deserialize_auth_data_fallback() {
let json = json!({ "session": "opaque_session_id" });
assert_matches!(from_json_value(json).unwrap(), AuthData::FallbackAcknowledgement(data));
assert_eq!(data.session, "opaque_session_id");
}
#[test]
fn serialize_uiaa_info() {
let flows = vec![AuthFlow::new(vec!["m.login.password".into(), "m.login.dummy".into()])];
let params = to_raw_json_value(&json!({
"example.type.baz": {
"example_key": "foobar"
}
}))
.unwrap();
let uiaa_info = assign!(UiaaInfo::new(flows, params), {
completed: vec!["m.login.password".into()],
});
let json = json!({
"flows": [{ "stages": ["m.login.password", "m.login.dummy"] }],
"completed": ["m.login.password"],
"params": {
"example.type.baz": {
"example_key": "foobar"
}
}
});
assert_eq!(to_json_value(uiaa_info).unwrap(), json);
}
#[test]
fn deserialize_uiaa_info() {
let json = json!({
"errcode": "M_FORBIDDEN",
"error": "Invalid password",
"completed": ["m.login.recaptcha"],
"flows": [
{
"stages": ["m.login.password"]
},
{
"stages": ["m.login.email.identity", "m.login.msisdn"]
}
],
"params": {
"example.type.baz": {
"example_key": "foobar"
}
},
"session": "xxxxxx"
});
let info = from_json_value::<UiaaInfo>(json).unwrap();
assert_eq!(info.completed, vec![AuthType::ReCaptcha]);
assert_eq!(info.flows.len(), 2);
assert_eq!(info.flows[0].stages, vec![AuthType::Password]);
assert_eq!(info.flows[1].stages, vec![AuthType::EmailIdentity, AuthType::Msisdn]);
assert_eq!(info.session.as_deref(), Some("xxxxxx"));
let auth_error = info.auth_error.unwrap();
assert_matches!(auth_error.kind, ErrorKind::Forbidden { .. });
assert_eq!(auth_error.message, "Invalid password");
assert_eq!(
from_json_str::<JsonValue>(info.params.get()).unwrap(),
json!({
"example.type.baz": {
"example_key": "foobar"
}
})
);
}
#[test]
fn try_uiaa_response_into_http_response() {
let flows = vec![AuthFlow::new(vec![AuthType::Password, AuthType::Dummy])];
let params = to_raw_json_value(&json!({
"example.type.baz": {
"example_key": "foobar"
}
}))
.unwrap();
let uiaa_info = assign!(UiaaInfo::new(flows, params), {
completed: vec![AuthType::ReCaptcha],
});
let uiaa_response =
UiaaResponse::AuthResponse(uiaa_info).try_into_http_response::<Vec<u8>>().unwrap();
let info = from_json_slice::<UiaaInfo>(uiaa_response.body()).unwrap();
assert_eq!(info.flows.len(), 1);
assert_eq!(info.flows[0].stages, vec![AuthType::Password, AuthType::Dummy]);
assert_eq!(info.completed, vec![AuthType::ReCaptcha]);
assert_eq!(info.session, None);
assert_matches!(info.auth_error, None);
assert_eq!(
from_json_str::<JsonValue>(info.params.get()).unwrap(),
json!({
"example.type.baz": {
"example_key": "foobar"
}
})
);
assert_eq!(uiaa_response.status(), http::status::StatusCode::UNAUTHORIZED);
}
#[test]
fn try_uiaa_response_from_http_response() {
let json = serde_json::to_string(&json!({
"errcode": "M_FORBIDDEN",
"error": "Invalid password",
"completed": ["m.login.recaptcha"],
"flows": [
{
"stages": ["m.login.password"]
},
{
"stages": ["m.login.email.identity", "m.login.msisdn"]
}
],
"params": {
"example.type.baz": {
"example_key": "foobar"
}
},
"session": "xxxxxx"
}))
.unwrap();
let http_response = http::Response::builder()
.status(http::StatusCode::UNAUTHORIZED)
.body(json.as_bytes())
.unwrap();
assert_matches!(
UiaaResponse::from_http_response(http_response),
UiaaResponse::AuthResponse(info)
);
assert_eq!(info.completed, vec![AuthType::ReCaptcha]);
assert_eq!(info.flows.len(), 2);
assert_eq!(info.flows[0].stages, vec![AuthType::Password]);
assert_eq!(info.flows[1].stages, vec![AuthType::EmailIdentity, AuthType::Msisdn]);
assert_eq!(info.session.as_deref(), Some("xxxxxx"));
let auth_error = info.auth_error.unwrap();
assert_matches!(auth_error.kind, ErrorKind::Forbidden { .. });
assert_eq!(auth_error.message, "Invalid password");
assert_eq!(
from_json_str::<JsonValue>(info.params.get()).unwrap(),
json!({
"example.type.baz": {
"example_key": "foobar"
}
})
);
}