1
0
mirror of https://github.com/matrix-org/matrix-authentication-service.git synced 2025-07-29 22:01:14 +03:00

Properly implement Display and FromStr for oauth2-types enums

Use SerializeDisplay and DeserializeFromStr derives.
Add tests for serialize and deserialize implemntations.
This commit is contained in:
Kévin Commaille
2022-09-12 15:11:47 +02:00
committed by Quentin Gliech
parent 94ba03a273
commit c4e495a84a
5 changed files with 413 additions and 98 deletions

73
Cargo.lock generated
View File

@ -1184,37 +1184,14 @@ dependencies = [
"cipher 0.3.0", "cipher 0.3.0",
] ]
[[package]]
name = "darling"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
dependencies = [
"darling_core 0.13.4",
"darling_macro 0.13.4",
]
[[package]] [[package]]
name = "darling" name = "darling"
version = "0.14.1" version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02" checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02"
dependencies = [ dependencies = [
"darling_core 0.14.1", "darling_core",
"darling_macro 0.14.1", "darling_macro",
]
[[package]]
name = "darling_core"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"syn",
] ]
[[package]] [[package]]
@ -1231,24 +1208,13 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "darling_macro"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
dependencies = [
"darling_core 0.13.4",
"quote",
"syn",
]
[[package]] [[package]]
name = "darling_macro" name = "darling_macro"
version = "0.14.1" version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5" checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5"
dependencies = [ dependencies = [
"darling_core 0.14.1", "darling_core",
"quote", "quote",
"syn", "syn",
] ]
@ -2912,7 +2878,6 @@ dependencies = [
"mas-jose", "mas-jose",
"parse-display", "parse-display",
"serde", "serde",
"serde-enum-str",
"serde_json", "serde_json",
"serde_with", "serde_with",
"sha2 0.10.5", "sha2 0.10.5",
@ -4062,36 +4027,6 @@ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]]
name = "serde-attributes"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3aba2af3c3b9cd6f3a919056dac6005b71fceecc1cdfa65c4df3912f64e07e60"
dependencies = [
"darling_core 0.13.4",
"serde-rename-rule",
"syn",
]
[[package]]
name = "serde-enum-str"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2a41bf2fc78a58589b9a6948bfc918c9b2dc918732f2ac14eed982ffb876b39"
dependencies = [
"darling 0.13.4",
"proc-macro2",
"quote",
"serde-attributes",
"syn",
]
[[package]]
name = "serde-rename-rule"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd2930103714ccef4f1fe5b6a5f2b6fdcfe462a6c802464714bd41e5b5097c33"
[[package]] [[package]]
name = "serde_bser" name = "serde_bser"
version = "0.3.1" version = "0.3.1"
@ -4172,7 +4107,7 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de337f322382fcdfbb21a014f7c224ee041a23785651db67b9827403178f698f" checksum = "de337f322382fcdfbb21a014f7c224ee041a23785651db67b9827403178f698f"
dependencies = [ dependencies = [
"darling 0.14.1", "darling",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn",

View File

@ -19,7 +19,6 @@ sha2 = "0.10.5"
data-encoding = "2.3.2" data-encoding = "2.3.2"
thiserror = "1.0.34" thiserror = "1.0.34"
itertools = "0.10.3" itertools = "0.10.3"
serde-enum-str = "0.2.5"
mas-iana = { path = "../iana" } mas-iana = { path = "../iana" }
mas-jose = { path = "../jose" } mas-jose = { path = "../jose" }

View File

@ -14,8 +14,9 @@
use std::borrow::Cow; use std::borrow::Cow;
use parse_display::{Display, FromStr};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_enum_str::{Deserialize_enum_str, Serialize_enum_str}; use serde_with::{DeserializeFromStr, SerializeDisplay};
/// A client error returned by an authorization server. /// A client error returned by an authorization server.
/// ///
@ -55,8 +56,8 @@ impl From<ClientErrorCode> for ClientError {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq, Serialize_enum_str, Deserialize_enum_str)] #[derive(Debug, Clone, PartialEq, Eq, Display, FromStr, SerializeDisplay, DeserializeFromStr)]
#[serde(rename_all = "snake_case")] #[display(style = "snake_case")]
pub enum ClientErrorCode { pub enum ClientErrorCode {
/// `invalid_request` /// `invalid_request`
/// ///
@ -225,7 +226,7 @@ pub enum ClientErrorCode {
InvalidClientMetadata, InvalidClientMetadata,
/// Another error code. /// Another error code.
#[serde(other)] #[display("{0}")]
Unknown(String), Unknown(String),
} }
@ -307,3 +308,195 @@ impl ClientErrorCode {
} }
} }
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn serialize_client_error_code() {
assert_eq!(
serde_json::to_string(&ClientErrorCode::InvalidRequest).unwrap(),
"\"invalid_request\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::InvalidClient).unwrap(),
"\"invalid_client\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::InvalidGrant).unwrap(),
"\"invalid_grant\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::UnauthorizedClient).unwrap(),
"\"unauthorized_client\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::UnsupportedGrantType).unwrap(),
"\"unsupported_grant_type\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::AccessDenied).unwrap(),
"\"access_denied\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::UnsupportedResponseType).unwrap(),
"\"unsupported_response_type\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::InvalidScope).unwrap(),
"\"invalid_scope\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::ServerError).unwrap(),
"\"server_error\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::TemporarilyUnavailable).unwrap(),
"\"temporarily_unavailable\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::InteractionRequired).unwrap(),
"\"interaction_required\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::LoginRequired).unwrap(),
"\"login_required\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::AccountSelectionRequired).unwrap(),
"\"account_selection_required\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::ConsentRequired).unwrap(),
"\"consent_required\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::InvalidRequestUri).unwrap(),
"\"invalid_request_uri\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::InvalidRequestObject).unwrap(),
"\"invalid_request_object\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::RequestNotSupported).unwrap(),
"\"request_not_supported\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::RequestUriNotSupported).unwrap(),
"\"request_uri_not_supported\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::RegistrationNotSupported).unwrap(),
"\"registration_not_supported\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::InvalidRedirectUri).unwrap(),
"\"invalid_redirect_uri\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::InvalidClientMetadata).unwrap(),
"\"invalid_client_metadata\""
);
assert_eq!(
serde_json::to_string(&ClientErrorCode::Unknown("unknown_error_code".to_owned()))
.unwrap(),
"\"unknown_error_code\""
);
}
#[test]
fn deserialize_client_error_code() {
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"invalid_request\"").unwrap(),
ClientErrorCode::InvalidRequest
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"invalid_client\"").unwrap(),
ClientErrorCode::InvalidClient
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"invalid_grant\"").unwrap(),
ClientErrorCode::InvalidGrant
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"unauthorized_client\"").unwrap(),
ClientErrorCode::UnauthorizedClient
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"unsupported_grant_type\"").unwrap(),
ClientErrorCode::UnsupportedGrantType
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"access_denied\"").unwrap(),
ClientErrorCode::AccessDenied
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"unsupported_response_type\"").unwrap(),
ClientErrorCode::UnsupportedResponseType
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"invalid_scope\"").unwrap(),
ClientErrorCode::InvalidScope
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"server_error\"").unwrap(),
ClientErrorCode::ServerError
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"temporarily_unavailable\"").unwrap(),
ClientErrorCode::TemporarilyUnavailable
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"interaction_required\"").unwrap(),
ClientErrorCode::InteractionRequired
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"login_required\"").unwrap(),
ClientErrorCode::LoginRequired
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"account_selection_required\"").unwrap(),
ClientErrorCode::AccountSelectionRequired
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"consent_required\"").unwrap(),
ClientErrorCode::ConsentRequired
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"invalid_request_uri\"").unwrap(),
ClientErrorCode::InvalidRequestUri
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"invalid_request_object\"").unwrap(),
ClientErrorCode::InvalidRequestObject
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"request_not_supported\"").unwrap(),
ClientErrorCode::RequestNotSupported
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"request_uri_not_supported\"").unwrap(),
ClientErrorCode::RequestUriNotSupported
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"registration_not_supported\"").unwrap(),
ClientErrorCode::RegistrationNotSupported
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"invalid_redirect_uri\"").unwrap(),
ClientErrorCode::InvalidRedirectUri
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"invalid_client_metadata\"").unwrap(),
ClientErrorCode::InvalidClientMetadata
);
assert_eq!(
serde_json::from_str::<ClientErrorCode>("\"unknown_error_code\"").unwrap(),
ClientErrorCode::Unknown("unknown_error_code".to_owned())
);
}
}

View File

@ -22,29 +22,36 @@ use mas_iana::{
PkceCodeChallengeMethod, PkceCodeChallengeMethod,
}, },
}; };
use parse_display::{Display, FromStr};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none; use serde_with::{skip_serializing_none, DeserializeFromStr, SerializeDisplay};
use thiserror::Error; use thiserror::Error;
use url::Url; use url::Url;
use crate::requests::{Display, GrantType, Prompt, ResponseMode}; use crate::requests::{Display, GrantType, Prompt, ResponseMode};
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash, Debug)] #[derive(
#[serde(rename_all = "lowercase")] SerializeDisplay, DeserializeFromStr, Clone, Copy, PartialEq, Eq, Hash, Debug, Display, FromStr,
)]
#[display(style = "lowercase")]
pub enum ApplicationType { pub enum ApplicationType {
Web, Web,
Native, Native,
} }
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash, Debug)] #[derive(
#[serde(rename_all = "lowercase")] SerializeDisplay, DeserializeFromStr, Clone, Copy, PartialEq, Eq, Hash, Debug, Display, FromStr,
)]
#[display(style = "lowercase")]
pub enum SubjectType { pub enum SubjectType {
Public, Public,
Pairwise, Pairwise,
} }
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash, Debug)] #[derive(
#[serde(rename_all = "lowercase")] SerializeDisplay, DeserializeFromStr, Clone, Copy, PartialEq, Eq, Hash, Debug, Display, FromStr,
)]
#[display(style = "lowercase")]
pub enum ClaimType { pub enum ClaimType {
Normal, Normal,
Aggregated, Aggregated,
@ -918,7 +925,7 @@ mod tests {
}; };
use url::Url; use url::Url;
use super::{ProviderMetadata, ProviderMetadataVerificationError, SubjectType}; use super::*;
fn valid_provider_metadata() -> (ProviderMetadata, Url) { fn valid_provider_metadata() -> (ProviderMetadata, Url) {
let issuer = Url::parse("https://localhost").unwrap(); let issuer = Url::parse("https://localhost").unwrap();
@ -1407,4 +1414,84 @@ mod tests {
Some(Url::parse("https://localhost/par?query#fragment").unwrap()); Some(Url::parse("https://localhost/par?query#fragment").unwrap());
metadata.validate(&issuer).unwrap(); metadata.validate(&issuer).unwrap();
} }
#[test]
fn serialize_application_type() {
assert_eq!(
serde_json::to_string(&ApplicationType::Web).unwrap(),
"\"web\""
);
assert_eq!(
serde_json::to_string(&ApplicationType::Native).unwrap(),
"\"native\""
);
}
#[test]
fn deserialize_application_type() {
assert_eq!(
serde_json::from_str::<ApplicationType>("\"web\"").unwrap(),
ApplicationType::Web
);
assert_eq!(
serde_json::from_str::<ApplicationType>("\"native\"").unwrap(),
ApplicationType::Native
);
}
#[test]
fn serialize_subject_type() {
assert_eq!(
serde_json::to_string(&SubjectType::Public).unwrap(),
"\"public\""
);
assert_eq!(
serde_json::to_string(&SubjectType::Pairwise).unwrap(),
"\"pairwise\""
);
}
#[test]
fn deserialize_subject_type() {
assert_eq!(
serde_json::from_str::<SubjectType>("\"public\"").unwrap(),
SubjectType::Public
);
assert_eq!(
serde_json::from_str::<SubjectType>("\"pairwise\"").unwrap(),
SubjectType::Pairwise
);
}
#[test]
fn serialize_claim_type() {
assert_eq!(
serde_json::to_string(&ClaimType::Normal).unwrap(),
"\"normal\""
);
assert_eq!(
serde_json::to_string(&ClaimType::Aggregated).unwrap(),
"\"aggregated\""
);
assert_eq!(
serde_json::to_string(&ClaimType::Distributed).unwrap(),
"\"distributed\""
);
}
#[test]
fn deserialize_claim_type() {
assert_eq!(
serde_json::from_str::<ClaimType>("\"normal\"").unwrap(),
ClaimType::Normal
);
assert_eq!(
serde_json::from_str::<ClaimType>("\"aggregated\"").unwrap(),
ClaimType::Aggregated
);
assert_eq!(
serde_json::from_str::<ClaimType>("\"distributed\"").unwrap(),
ClaimType::Distributed
);
}
} }

View File

@ -22,8 +22,8 @@ use mas_iana::oauth::{
use parse_display::{Display, FromStr}; use parse_display::{Display, FromStr};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_with::{ use serde_with::{
formats::SpaceSeparator, serde_as, skip_serializing_none, DisplayFromStr, DurationSeconds, formats::SpaceSeparator, serde_as, skip_serializing_none, DeserializeFromStr, DisplayFromStr,
StringWithSeparator, TimestampSeconds, DurationSeconds, SerializeDisplay, StringWithSeparator, TimestampSeconds,
}; };
use url::Url; use url::Url;
@ -46,10 +46,10 @@ use crate::scope::Scope;
Copy, Copy,
Display, Display,
FromStr, FromStr,
Serialize, SerializeDisplay,
Deserialize, DeserializeFromStr,
)] )]
#[serde(rename_all = "snake_case")] #[display(style = "snake_case")]
pub enum ResponseMode { pub enum ResponseMode {
/// Authorization Response parameters are encoded in the query string added /// Authorization Response parameters are encoded in the query string added
/// to the `redirect_uri`. /// to the `redirect_uri`.
@ -84,10 +84,10 @@ pub enum ResponseMode {
Copy, Copy,
Display, Display,
FromStr, FromStr,
Serialize, SerializeDisplay,
Deserialize, DeserializeFromStr,
)] )]
#[serde(rename_all = "snake_case")] #[display(style = "snake_case")]
pub enum Display { pub enum Display {
/// The Authorization Server should display the authentication and consent /// The Authorization Server should display the authentication and consent
/// UI consistent with a full User Agent page view. /// UI consistent with a full User Agent page view.
@ -129,11 +129,10 @@ impl Default for Display {
Copy, Copy,
Display, Display,
FromStr, FromStr,
Serialize, SerializeDisplay,
Deserialize, DeserializeFromStr,
)] )]
#[display(style = "snake_case")] #[display(style = "snake_case")]
#[serde(rename_all = "snake_case")]
pub enum Prompt { pub enum Prompt {
/// The Authorization Server must not display any authentication or consent /// The Authorization Server must not display any authentication or consent
/// user interface pages. /// user interface pages.
@ -366,10 +365,10 @@ pub struct ClientCredentialsGrant {
Copy, Copy,
Display, Display,
FromStr, FromStr,
Serialize, SerializeDisplay,
Deserialize, DeserializeFromStr,
)] )]
#[serde(rename_all = "snake_case")] #[display(style = "snake_case")]
pub enum GrantType { pub enum GrantType {
/// [`authorization_code`](https://www.rfc-editor.org/rfc/rfc6749#section-4.1) /// [`authorization_code`](https://www.rfc-editor.org/rfc/rfc6749#section-4.1)
AuthorizationCode, AuthorizationCode,
@ -387,11 +386,11 @@ pub enum GrantType {
Password, Password,
/// [`urn:ietf:params:oauth:grant-type:device_code`](https://www.rfc-editor.org/rfc/rfc8628) /// [`urn:ietf:params:oauth:grant-type:device_code`](https://www.rfc-editor.org/rfc/rfc8628)
#[serde(rename = "urn:ietf:params:oauth:grant-type:device_code")] #[display("urn:ietf:params:oauth:grant-type:device_code")]
DeviceCode, DeviceCode,
/// [`urn:openid:params:grant-type:ciba`](https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html) /// [`urn:openid:params:grant-type:ciba`](https://openid.net/specs/openid-client-initiated-backchannel-authentication-core-1_0.html)
#[serde(rename = "urn:openid:params:grant-type:ciba")] #[display("urn:openid:params:grant-type:ciba")]
ClientInitiatedBackchannelAuthentication, ClientInitiatedBackchannelAuthentication,
} }
@ -667,4 +666,106 @@ mod tests {
GrantType::ClientInitiatedBackchannelAuthentication GrantType::ClientInitiatedBackchannelAuthentication
); );
} }
#[test]
fn serialize_response_mode() {
assert_eq!(
serde_json::to_string(&ResponseMode::Query).unwrap(),
"\"query\""
);
assert_eq!(
serde_json::to_string(&ResponseMode::Fragment).unwrap(),
"\"fragment\""
);
assert_eq!(
serde_json::to_string(&ResponseMode::FormPost).unwrap(),
"\"form_post\""
);
}
#[test]
fn deserialize_response_mode() {
assert_eq!(
serde_json::from_str::<ResponseMode>("\"query\"").unwrap(),
ResponseMode::Query
);
assert_eq!(
serde_json::from_str::<ResponseMode>("\"fragment\"").unwrap(),
ResponseMode::Fragment
);
assert_eq!(
serde_json::from_str::<ResponseMode>("\"form_post\"").unwrap(),
ResponseMode::FormPost
);
}
#[test]
fn serialize_display() {
assert_eq!(serde_json::to_string(&Display::Page).unwrap(), "\"page\"");
assert_eq!(serde_json::to_string(&Display::Popup).unwrap(), "\"popup\"");
assert_eq!(serde_json::to_string(&Display::Touch).unwrap(), "\"touch\"");
assert_eq!(serde_json::to_string(&Display::Wap).unwrap(), "\"wap\"");
}
#[test]
fn deserialize_display() {
assert_eq!(
serde_json::from_str::<Display>("\"page\"").unwrap(),
Display::Page
);
assert_eq!(
serde_json::from_str::<Display>("\"popup\"").unwrap(),
Display::Popup
);
assert_eq!(
serde_json::from_str::<Display>("\"touch\"").unwrap(),
Display::Touch
);
assert_eq!(
serde_json::from_str::<Display>("\"wap\"").unwrap(),
Display::Wap
);
}
#[test]
fn serialize_prompt() {
assert_eq!(serde_json::to_string(&Prompt::None).unwrap(), "\"none\"");
assert_eq!(serde_json::to_string(&Prompt::Login).unwrap(), "\"login\"");
assert_eq!(
serde_json::to_string(&Prompt::Consent).unwrap(),
"\"consent\""
);
assert_eq!(
serde_json::to_string(&Prompt::SelectAccount).unwrap(),
"\"select_account\""
);
assert_eq!(
serde_json::to_string(&Prompt::Create).unwrap(),
"\"create\""
);
}
#[test]
fn deserialize_prompt() {
assert_eq!(
serde_json::from_str::<Prompt>("\"none\"").unwrap(),
Prompt::None
);
assert_eq!(
serde_json::from_str::<Prompt>("\"login\"").unwrap(),
Prompt::Login
);
assert_eq!(
serde_json::from_str::<Prompt>("\"consent\"").unwrap(),
Prompt::Consent
);
assert_eq!(
serde_json::from_str::<Prompt>("\"select_account\"").unwrap(),
Prompt::SelectAccount
);
assert_eq!(
serde_json::from_str::<Prompt>("\"create\"").unwrap(),
Prompt::Create
);
}
} }