296 lines
8.3 KiB
Rust
296 lines
8.3 KiB
Rust
use assign::assign;
|
|
use matches::assert_matches;
|
|
use ruma_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,
|
|
};
|
|
|
|
use ruma_client_api::{
|
|
error::{ErrorBody, ErrorKind},
|
|
r0::uiaa::{
|
|
self, AuthData, AuthFlow, AuthType, IncomingAuthData, IncomingUserIdentifier, UiaaInfo,
|
|
UiaaResponse,
|
|
},
|
|
};
|
|
|
|
#[test]
|
|
fn deserialize_user_identifier() {
|
|
assert_matches!(
|
|
from_json_value(json!({
|
|
"type": "m.id.user",
|
|
"user": "cheeky_monkey"
|
|
}))
|
|
.unwrap(),
|
|
IncomingUserIdentifier::MatrixId(id)
|
|
if id == "cheeky_monkey"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn serialize_auth_data_token() {
|
|
let auth_data = AuthData::Token(
|
|
assign!(uiaa::Token::new("mytoken", "txn123".into()), { session: Some("session") }),
|
|
);
|
|
|
|
assert_matches!(
|
|
to_json_value(auth_data),
|
|
Ok(val) if val == json!({
|
|
"type": "m.login.token",
|
|
"token": "mytoken",
|
|
"txn_id": "txn123",
|
|
"session": "session",
|
|
})
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn deserialize_auth_data_direct_request() {
|
|
let json = json!({
|
|
"type": "m.login.token",
|
|
"token": "mytoken",
|
|
"txn_id": "txn123",
|
|
"session": "session",
|
|
});
|
|
|
|
assert_matches!(
|
|
from_json_value(json),
|
|
Ok(IncomingAuthData::Token(
|
|
uiaa::IncomingToken { token, txn_id, session: Some(session), .. },
|
|
))
|
|
if token == "mytoken"
|
|
&& txn_id == "txn123"
|
|
&& session == "session"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(feature = "unstable-spec")] // todo: v1.2
|
|
fn serialize_auth_data_registration_token() {
|
|
let auth_data = AuthData::RegistrationToken(
|
|
assign!(uiaa::RegistrationToken::new("mytoken"), { session: Some("session") }),
|
|
);
|
|
|
|
assert_matches!(
|
|
to_json_value(auth_data),
|
|
Ok(val) if val == json!({
|
|
"type": "m.login.registration_token",
|
|
"token": "mytoken",
|
|
"session": "session",
|
|
})
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(feature = "unstable-spec")] // todo: v1.2
|
|
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(IncomingAuthData::RegistrationToken(
|
|
uiaa::IncomingRegistrationToken { token, session: Some(session), .. },
|
|
))
|
|
if token == "mytoken" && session == "session"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn serialize_auth_data_fallback() {
|
|
let auth_data = AuthData::FallbackAcknowledgement(uiaa::FallbackAcknowledgement::new("ZXY000"));
|
|
|
|
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(),
|
|
IncomingAuthData::FallbackAcknowledgement(
|
|
uiaa::IncomingFallbackAcknowledgement { session, .. },
|
|
)
|
|
if 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"
|
|
});
|
|
|
|
assert_matches!(
|
|
from_json_value::<UiaaInfo>(json).unwrap(),
|
|
UiaaInfo {
|
|
auth_error: Some(ErrorBody {
|
|
kind: ErrorKind::Forbidden,
|
|
message: error_message,
|
|
}),
|
|
completed,
|
|
flows,
|
|
params,
|
|
session: Some(session),
|
|
..
|
|
} if error_message == "Invalid password"
|
|
&& completed == vec![AuthType::ReCaptcha]
|
|
&& matches!(
|
|
flows.as_slice(),
|
|
[f1, f2]
|
|
if f1.stages == vec![AuthType::Password]
|
|
&& f2.stages == vec![AuthType::EmailIdentity, AuthType::Msisdn]
|
|
)
|
|
&& from_json_str::<JsonValue>(params.get()).unwrap() == json!({
|
|
"example.type.baz": {
|
|
"example_key": "foobar"
|
|
}
|
|
})
|
|
&& session == "xxxxxx"
|
|
);
|
|
}
|
|
|
|
#[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();
|
|
|
|
assert_matches!(
|
|
from_json_slice::<UiaaInfo>(uiaa_response.body()).unwrap(),
|
|
UiaaInfo {
|
|
flows,
|
|
completed,
|
|
params,
|
|
session: None,
|
|
auth_error: None,
|
|
..
|
|
} if matches!(
|
|
flows.as_slice(),
|
|
[flow] if flow.stages == vec![AuthType::Password, AuthType::Dummy]
|
|
) && completed == vec![AuthType::ReCaptcha]
|
|
&& from_json_str::<JsonValue>(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();
|
|
|
|
let parsed_uiaa_info = match UiaaResponse::try_from_http_response(http_response).unwrap() {
|
|
UiaaResponse::AuthResponse(uiaa_info) => uiaa_info,
|
|
_ => panic!("Expected UiaaResponse::AuthResponse"),
|
|
};
|
|
|
|
assert_matches!(
|
|
parsed_uiaa_info,
|
|
UiaaInfo {
|
|
auth_error: Some(ErrorBody {
|
|
kind: ErrorKind::Forbidden,
|
|
message: error_message,
|
|
}),
|
|
completed,
|
|
flows,
|
|
params,
|
|
session: Some(session),
|
|
..
|
|
} if error_message == "Invalid password"
|
|
&& completed == vec![AuthType::ReCaptcha]
|
|
&& matches!(
|
|
flows.as_slice(),
|
|
[f1, f2]
|
|
if f1.stages == vec![AuthType::Password]
|
|
&& f2.stages == vec![AuthType::EmailIdentity, AuthType::Msisdn]
|
|
)
|
|
&& from_json_str::<JsonValue>(params.get()).unwrap() == json!({
|
|
"example.type.baz": {
|
|
"example_key": "foobar"
|
|
}
|
|
})
|
|
&& session == "xxxxxx"
|
|
);
|
|
}
|