diff --git a/Cargo.lock b/Cargo.lock index b67a4a65f..61fc0b4ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3723,6 +3723,7 @@ dependencies = [ "mas-data-model", "mas-i18n", "mas-iana", + "mas-policy", "mas-router", "mas-spa", "minijinja", diff --git a/crates/handlers/src/compat/login_sso_complete.rs b/crates/handlers/src/compat/login_sso_complete.rs index 9ede9a923..b0735ffce 100644 --- a/crates/handlers/src/compat/login_sso_complete.rs +++ b/crates/handlers/src/compat/login_sso_complete.rs @@ -135,15 +135,10 @@ pub async fn get( }) .await?; if !res.valid() { - let ctx = CompatLoginPolicyViolationContext::for_violations( - res.violations - .into_iter() - .filter_map(|v| Some(v.code?.as_str())) - .collect(), - ) - .with_session(session) - .with_csrf(csrf_token.form_value()) - .with_language(locale); + let ctx = CompatLoginPolicyViolationContext::for_violations(res.violations) + .with_session(session) + .with_csrf(csrf_token.form_value()) + .with_language(locale); let content = templates.render_compat_login_policy_violation(&ctx)?; @@ -269,15 +264,10 @@ pub async fn post( if !res.valid() { let (csrf_token, cookie_jar) = cookie_jar.csrf_token(&clock, &mut rng); - let ctx = CompatLoginPolicyViolationContext::for_violations( - res.violations - .into_iter() - .filter_map(|v| Some(v.code?.as_str())) - .collect(), - ) - .with_session(session) - .with_csrf(csrf_token.form_value()) - .with_language(locale); + let ctx = CompatLoginPolicyViolationContext::for_violations(res.violations) + .with_session(session) + .with_csrf(csrf_token.form_value()) + .with_language(locale); let content = templates.render_compat_login_policy_violation(&ctx)?; diff --git a/crates/policy/src/model.rs b/crates/policy/src/model.rs index 3f6a72d66..a9f5fb502 100644 --- a/crates/policy/src/model.rs +++ b/crates/policy/src/model.rs @@ -17,7 +17,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; /// A well-known policy code. -#[derive(Deserialize, Debug, Clone, Copy, JsonSchema, PartialEq, Eq)] +#[derive(Serialize, Deserialize, Debug, Clone, Copy, JsonSchema, PartialEq, Eq)] #[serde(rename_all = "kebab-case")] pub enum Code { /// The username is too short. @@ -75,7 +75,7 @@ impl Code { } /// A single violation of a policy. -#[derive(Deserialize, Debug, JsonSchema)] +#[derive(Serialize, Deserialize, Debug, JsonSchema)] pub struct Violation { pub msg: String, pub redirect_uri: Option, diff --git a/crates/templates/Cargo.toml b/crates/templates/Cargo.toml index 46ff80c74..d9c1bb019 100644 --- a/crates/templates/Cargo.toml +++ b/crates/templates/Cargo.toml @@ -41,6 +41,7 @@ oauth2-types.workspace = true mas-data-model.workspace = true mas-i18n.workspace = true mas-iana.workspace = true +mas-policy.workspace = true mas-router.workspace = true mas-spa.workspace = true diff --git a/crates/templates/src/context.rs b/crates/templates/src/context.rs index 85d3f6e3e..bee16efbd 100644 --- a/crates/templates/src/context.rs +++ b/crates/templates/src/context.rs @@ -28,6 +28,7 @@ use mas_data_model::{ }; use mas_i18n::DataLocale; use mas_iana::jose::JsonWebSignatureAlg; +use mas_policy::{Violation, ViolationCode}; use mas_router::{Account, GraphQL, PostAuthAction, UrlBuilder}; use oauth2_types::scope::{OPENID, Scope}; use rand::{ @@ -863,7 +864,7 @@ impl PolicyViolationContext { /// Context used by the `compat_login_policy_violation.html` template #[derive(Serialize)] pub struct CompatLoginPolicyViolationContext { - violation_codes: Vec<&'static str>, + violations: Vec, } impl TemplateContext for CompatLoginPolicyViolationContext { @@ -876,11 +877,14 @@ impl TemplateContext for CompatLoginPolicyViolationContext { Self: Sized, { sample_list(vec![ + CompatLoginPolicyViolationContext { violations: vec![] }, CompatLoginPolicyViolationContext { - violation_codes: vec![], - }, - CompatLoginPolicyViolationContext { - violation_codes: vec!["too-many-sessions"], + violations: vec![Violation { + msg: "user has too many active sessions".to_owned(), + redirect_uri: None, + field: None, + code: Some(ViolationCode::TooManySessions), + }], }, ]) } @@ -888,13 +892,10 @@ impl TemplateContext for CompatLoginPolicyViolationContext { impl CompatLoginPolicyViolationContext { /// Constructs a context for the compatibility login policy violation page - /// given the list of violations' codes. - /// - /// TODO maybe this is not very nice, not sure what the API boundary should - /// be + /// given the list of violations #[must_use] - pub const fn for_violations(violation_codes: Vec<&'static str>) -> Self { - Self { violation_codes } + pub const fn for_violations(violations: Vec) -> Self { + Self { violations } } }