Add UIAA error types
This commit is contained in:
parent
3ecc114ca6
commit
0d080a7ffa
10
CHANGELOG.md
10
CHANGELOG.md
@ -3,9 +3,13 @@
|
||||
Breaking changes:
|
||||
|
||||
* Add `server_name` parameter to `r0::join::join_room_by_id_or_alias`
|
||||
* Add `auth_parameters` to `r0::account::AuthenticationData`
|
||||
* Modify `r0::account::AuthenticationData`:
|
||||
- Rename to `AuthData`
|
||||
- Change to an enum to facilitate fallback auth acknowledgements
|
||||
- Add `auth_parameters` field
|
||||
- Move to `r0::uiaa` module
|
||||
* Add `room_network` parameter to `r0::directory::get_public_rooms_filtered` to
|
||||
represent `include_all_networks` and `third_party_instance_id` Matrix fields.
|
||||
represent `include_all_networks` and `third_party_instance_id` Matrix fields
|
||||
* Update `r0::account::register` endpoint:
|
||||
* Remove `bind_email` request field (removed in r0.6.0)
|
||||
* Remove `inhibit_login` request field, make `access_token` and `device_id` response fields optional (added in r0.4.0)
|
||||
@ -19,7 +23,7 @@ Breaking changes:
|
||||
|
||||
Improvements:
|
||||
|
||||
* Add types for User-Interactive Authentication API: `r0::account::{UserInteractiveAuthenticationInfo, AuthenticationFlow}`
|
||||
* Add types for User-Interactive Authentication API: `r0::uiaa::{AuthFlow, UiaaInfo, UiaaResponse}`
|
||||
* Add missing serde attributes to `get_content_thumbnail` query parameters
|
||||
|
||||
# 0.7.2
|
||||
|
@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize};
|
||||
/// An enum for the error kind. Items may contain additional information.
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
#[serde(tag = "errcode")]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
pub enum ErrorKind {
|
||||
/// M_FORBIDDEN
|
||||
#[serde(rename = "M_FORBIDDEN")]
|
||||
@ -98,6 +99,7 @@ pub enum ErrorKind {
|
||||
|
||||
/// A Matrix Error without a status code
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
pub struct ErrorBody {
|
||||
/// A value which can be used to handle an error message
|
||||
#[serde(flatten)]
|
||||
|
@ -30,5 +30,6 @@ pub mod sync;
|
||||
pub mod tag;
|
||||
pub mod thirdparty;
|
||||
pub mod typing;
|
||||
pub mod uiaa;
|
||||
pub mod user_directory;
|
||||
pub mod voip;
|
||||
|
@ -17,48 +17,8 @@ pub mod unbind_3pid;
|
||||
|
||||
pub mod whoami;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Additional authentication information for the user-interactive authentication API.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct AuthenticationData {
|
||||
/// The login type that the client is attempting to complete.
|
||||
#[serde(rename = "type")]
|
||||
pub kind: String,
|
||||
/// The value of the session key given by the homeserver.
|
||||
pub session: Option<String>,
|
||||
/// Parameters submitted for a particular authentication stage.
|
||||
#[serde(flatten)]
|
||||
pub auth_parameters: BTreeMap<String, serde_json::Value>,
|
||||
}
|
||||
|
||||
/// Information about available authentication flows and status for
|
||||
/// User-Interactive Authenticiation API.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct UserInteractiveAuthenticationInfo {
|
||||
/// List of authentication flows available for this endpoint.
|
||||
pub flows: Vec<AuthenticationFlow>,
|
||||
/// List of stages in the current flow completed by the client.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub completed: Vec<String>,
|
||||
/// Authentication parameters required for the client to complete authentication.
|
||||
pub params: serde_json::Value,
|
||||
/// Session key for client to use to complete authentication.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub session: Option<String>,
|
||||
}
|
||||
|
||||
/// Description of steps required to authenticate via the User-Interactive
|
||||
/// Authentication API.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct AuthenticationFlow {
|
||||
/// Ordered list of stages required to complete authentication.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub stages: Vec<String>,
|
||||
}
|
||||
|
||||
/// Additional authentication information for requestToken endpoints.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct IdentityServerInfo {
|
||||
|
31
src/r0/account/add_3pid.rs
Normal file
31
src/r0/account/add_3pid.rs
Normal file
@ -0,0 +1,31 @@
|
||||
//! [POST /_matrix/client/r0/account/3pid/add](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-account-3pid-add)
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use crate::r0::uiaa::{AuthData, UiaaResponse};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Add contact information to a user's account",
|
||||
method: POST,
|
||||
name: "add_3pid",
|
||||
path: "/_matrix/client/r0/account/3pid/add",
|
||||
rate_limited: true,
|
||||
requires_authentication: true,
|
||||
}
|
||||
|
||||
request {
|
||||
/// Additional information for the User-Interactive Authentication API.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub auth: Option<AuthData>,
|
||||
/// Client-generated secret string used to protect this session.
|
||||
pub client_secret: String,
|
||||
/// The session identifier given by the identity server.
|
||||
pub sid: String,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: UiaaResponse
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use super::AuthenticationData;
|
||||
use crate::r0::uiaa::{AuthData, UiaaResponse};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
@ -18,10 +18,10 @@ ruma_api! {
|
||||
/// The new password for the account.
|
||||
pub new_password: String,
|
||||
/// Additional authentication information for the user-interactive authentication API.
|
||||
pub auth: Option<AuthenticationData>,
|
||||
pub auth: Option<AuthData>,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
error: UiaaResponse
|
||||
}
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
use ruma_api::ruma_api;
|
||||
|
||||
use super::{AuthenticationData, ThirdPartyIdRemovalStatus};
|
||||
use crate::r0::uiaa::{AuthData, UiaaResponse};
|
||||
|
||||
use super::ThirdPartyIdRemovalStatus;
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
@ -17,7 +19,7 @@ ruma_api! {
|
||||
request {
|
||||
/// Additional authentication information for the user-interactive authentication API.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub auth: Option<AuthenticationData>,
|
||||
pub auth: Option<AuthData>,
|
||||
/// Identity server from which to unbind the user's third party
|
||||
/// identifier.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
@ -29,5 +31,5 @@ ruma_api! {
|
||||
pub id_server_unbind_result: ThirdPartyIdRemovalStatus,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
error: UiaaResponse
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use ruma_api::ruma_api;
|
||||
use ruma_identifiers::{DeviceId, UserId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use super::AuthenticationData;
|
||||
use crate::r0::uiaa::{AuthData, UiaaResponse};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
@ -46,7 +46,7 @@ ruma_api! {
|
||||
/// It should be left empty, or omitted, unless an earlier call returned an response
|
||||
/// with status code 401.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub auth: Option<AuthenticationData>,
|
||||
pub auth: Option<AuthData>,
|
||||
/// Kind of account to register
|
||||
///
|
||||
/// Defaults to `User` if omitted.
|
||||
@ -73,7 +73,7 @@ ruma_api! {
|
||||
pub device_id: Option<DeviceId>,
|
||||
}
|
||||
|
||||
error: crate::Error
|
||||
error: UiaaResponse
|
||||
}
|
||||
|
||||
/// The kind of account being registered.
|
||||
|
@ -1,9 +1,10 @@
|
||||
//! [DELETE /_matrix/client/r0/devices/{deviceId}](https://matrix.org/docs/spec/client_server/r0.6.0#delete-matrix-client-r0-devices-deviceid)
|
||||
|
||||
use crate::r0::account::AuthenticationData;
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::DeviceId;
|
||||
|
||||
use crate::r0::uiaa::{AuthData, UiaaResponse};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Delete a device for authenticated user.",
|
||||
@ -20,10 +21,10 @@ ruma_api! {
|
||||
pub device_id: DeviceId,
|
||||
/// Additional authentication information for the user-interactive authentication API.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub auth: Option<AuthenticationData>,
|
||||
pub auth: Option<AuthData>,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
error: UiaaResponse
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
//! [POST /_matrix/client/r0/delete_devices](https://matrix.org/docs/spec/client_server/r0.6.0#post-matrix-client-r0-delete-devices)
|
||||
|
||||
use crate::r0::account::AuthenticationData;
|
||||
use ruma_api::ruma_api;
|
||||
use ruma_identifiers::DeviceId;
|
||||
|
||||
use crate::r0::uiaa::{AuthData, UiaaResponse};
|
||||
|
||||
ruma_api! {
|
||||
metadata {
|
||||
description: "Delete specified devices.",
|
||||
@ -20,10 +21,10 @@ ruma_api! {
|
||||
|
||||
/// Additional authentication information for the user-interactive authentication API.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub auth: Option<AuthenticationData>,
|
||||
pub auth: Option<AuthData>,
|
||||
}
|
||||
|
||||
response {}
|
||||
|
||||
error: crate::Error
|
||||
error: UiaaResponse
|
||||
}
|
||||
|
363
src/r0/uiaa.rs
Normal file
363
src/r0/uiaa.rs
Normal file
@ -0,0 +1,363 @@
|
||||
//! Module for User-Interactive Authentication API types.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use ruma_api::{error::ResponseDeserializationError, EndpointError};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value as JsonValue;
|
||||
|
||||
use crate::error::{Error as MatrixError, ErrorBody};
|
||||
|
||||
/// Additional authentication information for the user-interactive authentication API.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[serde(untagged)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
pub enum AuthData {
|
||||
/// Used for sending UIAA authentication requests to the homeserver directly
|
||||
/// from the client.
|
||||
DirectRequest {
|
||||
/// The login type that the client is attempting to complete.
|
||||
#[serde(rename = "type")]
|
||||
kind: String,
|
||||
/// The value of the session key given by the homeserver.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
session: Option<String>,
|
||||
/// Parameters submitted for a particular authentication stage.
|
||||
#[serde(flatten)]
|
||||
auth_parameters: BTreeMap<String, JsonValue>,
|
||||
},
|
||||
/// Used by the client to acknowledge that the user has completed a UIAA
|
||||
/// stage through the fallback method.
|
||||
FallbackAcknowledgement {
|
||||
/// The value of the session key given by the homeserver.
|
||||
session: String,
|
||||
},
|
||||
}
|
||||
|
||||
/// Information about available authentication flows and status for
|
||||
/// User-Interactive Authenticiation API.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
pub struct UiaaInfo {
|
||||
/// List of authentication flows available for this endpoint.
|
||||
pub flows: Vec<AuthFlow>,
|
||||
/// List of stages in the current flow completed by the client.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub completed: Vec<String>,
|
||||
/// Authentication parameters required for the client to complete authentication.
|
||||
pub params: JsonValue,
|
||||
/// Session key for client to use to complete authentication.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub session: Option<String>,
|
||||
/// Authentication-related errors for previous request returned by homeserver.
|
||||
#[serde(flatten, skip_serializing_if = "Option::is_none")]
|
||||
pub auth_error: Option<ErrorBody>,
|
||||
}
|
||||
|
||||
/// Description of steps required to authenticate via the User-Interactive
|
||||
/// Authentication API.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
pub struct AuthFlow {
|
||||
/// Ordered list of stages required to complete authentication.
|
||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||
pub stages: Vec<String>,
|
||||
}
|
||||
|
||||
/// Contains either a User-Interactive Authentication API response body or a
|
||||
/// Matrix error.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum UiaaResponse {
|
||||
/// User-Interactive Authentication API response
|
||||
AuthResponse(UiaaInfo),
|
||||
/// Matrix error response
|
||||
MatrixError(MatrixError),
|
||||
}
|
||||
|
||||
impl From<MatrixError> for UiaaResponse {
|
||||
fn from(error: MatrixError) -> Self {
|
||||
Self::MatrixError(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl EndpointError for UiaaResponse {
|
||||
fn try_from_response(
|
||||
response: http::Response<Vec<u8>>,
|
||||
) -> Result<Self, ResponseDeserializationError> {
|
||||
if response.status() == http::StatusCode::UNAUTHORIZED {
|
||||
if let Ok(authentication_info) = serde_json::from_slice::<UiaaInfo>(response.body()) {
|
||||
return Ok(UiaaResponse::AuthResponse(authentication_info));
|
||||
}
|
||||
}
|
||||
|
||||
MatrixError::try_from_response(response).map(From::from)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UiaaResponse> for http::Response<Vec<u8>> {
|
||||
fn from(uiaa_response: UiaaResponse) -> http::Response<Vec<u8>> {
|
||||
match uiaa_response {
|
||||
UiaaResponse::AuthResponse(authentication_info) => http::Response::builder()
|
||||
.header(http::header::CONTENT_TYPE, "application/json")
|
||||
.status(&http::StatusCode::UNAUTHORIZED)
|
||||
.body(serde_json::to_vec(&authentication_info).unwrap())
|
||||
.unwrap(),
|
||||
UiaaResponse::MatrixError(error) => http::Response::from(error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use ruma_api::EndpointError;
|
||||
use serde_json::{
|
||||
from_value as from_json_value, json, to_value as to_json_value, Value as JsonValue,
|
||||
};
|
||||
|
||||
use super::{AuthData, AuthFlow, UiaaInfo, UiaaResponse};
|
||||
use crate::error::{ErrorBody, ErrorKind};
|
||||
|
||||
#[test]
|
||||
fn test_serialize_authentication_data_direct_request() {
|
||||
let mut auth_parameters = BTreeMap::new();
|
||||
auth_parameters.insert(
|
||||
"example_credential".into(),
|
||||
JsonValue::String("verypoorsharedsecret".into()),
|
||||
);
|
||||
let authentication_data = AuthData::DirectRequest {
|
||||
kind: "example.type.foo".to_string(),
|
||||
session: Some("ZXY000".to_string()),
|
||||
auth_parameters,
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
json!({ "type": "example.type.foo", "session": "ZXY000", "example_credential": "verypoorsharedsecret" }),
|
||||
to_json_value(authentication_data).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_authentication_data_direct_request() {
|
||||
let mut auth_parameters = BTreeMap::new();
|
||||
auth_parameters.insert(
|
||||
"example_credential".into(),
|
||||
JsonValue::String("verypoorsharedsecret".into()),
|
||||
);
|
||||
let authentication_data = AuthData::DirectRequest {
|
||||
kind: "example.type.foo".into(),
|
||||
session: Some("opaque_session_id".to_string()),
|
||||
auth_parameters,
|
||||
};
|
||||
let json = json!({ "type": "example.type.foo", "session": "opaque_session_id", "example_credential": "verypoorsharedsecret", });
|
||||
|
||||
assert_eq!(
|
||||
from_json_value::<AuthData>(json).unwrap(),
|
||||
authentication_data
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_authentication_data_fallback() {
|
||||
let authentication_data = AuthData::FallbackAcknowledgement {
|
||||
session: "ZXY000".to_string(),
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
json!({ "session": "ZXY000" }),
|
||||
to_json_value(authentication_data).unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_authentication_data_fallback() {
|
||||
let authentication_data = AuthData::FallbackAcknowledgement {
|
||||
session: "opaque_session_id".to_string(),
|
||||
};
|
||||
let json = json!({ "session": "opaque_session_id" });
|
||||
|
||||
assert_eq!(
|
||||
from_json_value::<AuthData>(json).unwrap(),
|
||||
authentication_data
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_serialize_uiaa_info() {
|
||||
let params = json!({
|
||||
"example.type.baz": {
|
||||
"example_key": "foobar"
|
||||
}
|
||||
});
|
||||
|
||||
let uiaa_info = UiaaInfo {
|
||||
flows: vec![AuthFlow {
|
||||
stages: vec!["m.login.password".to_string(), "m.login.dummy".to_string()],
|
||||
}],
|
||||
completed: vec!["m.login.password".to_string()],
|
||||
params,
|
||||
session: None,
|
||||
auth_error: None,
|
||||
};
|
||||
|
||||
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 test_deserialize_uiaa_info() {
|
||||
let json = json!({
|
||||
"errcode": "M_FORBIDDEN",
|
||||
"error": "Invalid password",
|
||||
"completed": [ "example.type.foo" ],
|
||||
"flows": [
|
||||
{
|
||||
"stages": [ "example.type.foo", "example.type.bar" ]
|
||||
},
|
||||
{
|
||||
"stages": [ "example.type.foo", "example.type.baz" ]
|
||||
}
|
||||
],
|
||||
"params": {
|
||||
"example.type.baz": {
|
||||
"example_key": "foobar"
|
||||
}
|
||||
},
|
||||
"session": "xxxxxx"
|
||||
});
|
||||
|
||||
let uiaa_info = UiaaInfo {
|
||||
auth_error: Some(ErrorBody {
|
||||
kind: ErrorKind::Forbidden,
|
||||
message: "Invalid password".to_string(),
|
||||
}),
|
||||
completed: vec!["example.type.foo".to_string()],
|
||||
flows: vec![
|
||||
AuthFlow {
|
||||
stages: vec![
|
||||
"example.type.foo".to_string(),
|
||||
"example.type.bar".to_string(),
|
||||
],
|
||||
},
|
||||
AuthFlow {
|
||||
stages: vec![
|
||||
"example.type.foo".to_string(),
|
||||
"example.type.baz".to_string(),
|
||||
],
|
||||
},
|
||||
],
|
||||
params: json!({
|
||||
"example.type.baz": {
|
||||
"example_key": "foobar"
|
||||
}
|
||||
}),
|
||||
session: Some("xxxxxx".to_string()),
|
||||
};
|
||||
assert_eq!(from_json_value::<UiaaInfo>(json).unwrap(), uiaa_info);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_uiaa_response_into_http_response() {
|
||||
let params = json!({
|
||||
"example.type.baz": {
|
||||
"example_key": "foobar"
|
||||
}
|
||||
});
|
||||
|
||||
let uiaa_info = UiaaInfo {
|
||||
flows: vec![AuthFlow {
|
||||
stages: vec!["m.login.password".to_string(), "m.login.dummy".to_string()],
|
||||
}],
|
||||
completed: vec!["m.login.password".to_string()],
|
||||
params,
|
||||
session: None,
|
||||
auth_error: None,
|
||||
};
|
||||
let uiaa_response: http::Response<Vec<u8>> =
|
||||
UiaaResponse::AuthResponse(uiaa_info.clone()).into();
|
||||
|
||||
assert_eq!(
|
||||
serde_json::from_slice::<UiaaInfo>(uiaa_response.body()).unwrap(),
|
||||
uiaa_info,
|
||||
);
|
||||
assert_eq!(
|
||||
uiaa_response.status(),
|
||||
http::status::StatusCode::UNAUTHORIZED
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_uiaa_response_from_http_response() {
|
||||
let json = serde_json::to_string(&json!({
|
||||
"errcode": "M_FORBIDDEN",
|
||||
"error": "Invalid password",
|
||||
"completed": [ "example.type.foo" ],
|
||||
"flows": [
|
||||
{
|
||||
"stages": [ "example.type.foo", "example.type.bar" ]
|
||||
},
|
||||
{
|
||||
"stages": [ "example.type.foo", "example.type.baz" ]
|
||||
}
|
||||
],
|
||||
"params": {
|
||||
"example.type.baz": {
|
||||
"example_key": "foobar"
|
||||
}
|
||||
},
|
||||
"session": "xxxxxx"
|
||||
}))
|
||||
.unwrap();
|
||||
let http_response = http::Response::builder()
|
||||
.status(http::StatusCode::UNAUTHORIZED)
|
||||
.body(json.into())
|
||||
.unwrap();
|
||||
|
||||
let uiaa_info = UiaaInfo {
|
||||
auth_error: Some(ErrorBody {
|
||||
kind: ErrorKind::Forbidden,
|
||||
message: "Invalid password".to_string(),
|
||||
}),
|
||||
completed: vec!["example.type.foo".to_string()],
|
||||
flows: vec![
|
||||
AuthFlow {
|
||||
stages: vec![
|
||||
"example.type.foo".to_string(),
|
||||
"example.type.bar".to_string(),
|
||||
],
|
||||
},
|
||||
AuthFlow {
|
||||
stages: vec![
|
||||
"example.type.foo".to_string(),
|
||||
"example.type.baz".to_string(),
|
||||
],
|
||||
},
|
||||
],
|
||||
params: json!({
|
||||
"example.type.baz": {
|
||||
"example_key": "foobar"
|
||||
}
|
||||
}),
|
||||
session: Some("xxxxxx".to_string()),
|
||||
};
|
||||
|
||||
let parsed_uiaa_info = match UiaaResponse::try_from_response(http_response) {
|
||||
Ok(auth_response) => match auth_response {
|
||||
UiaaResponse::AuthResponse(uiaa_info) => Some(uiaa_info),
|
||||
_ => None,
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
|
||||
assert_eq!(parsed_uiaa_info, Some(uiaa_info));
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user