diff --git a/crates/templates/src/context.rs b/crates/templates/src/context.rs index 4ed09c3e1..85d3f6e3e 100644 --- a/crates/templates/src/context.rs +++ b/crates/templates/src/context.rs @@ -860,6 +860,44 @@ impl PolicyViolationContext { } } +/// Context used by the `compat_login_policy_violation.html` template +#[derive(Serialize)] +pub struct CompatLoginPolicyViolationContext { + violation_codes: Vec<&'static str>, +} + +impl TemplateContext for CompatLoginPolicyViolationContext { + fn sample( + _now: chrono::DateTime, + _rng: &mut R, + _locales: &[DataLocale], + ) -> BTreeMap + where + Self: Sized, + { + sample_list(vec![ + CompatLoginPolicyViolationContext { + violation_codes: vec![], + }, + CompatLoginPolicyViolationContext { + violation_codes: vec!["too-many-sessions"], + }, + ]) + } +} + +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 + #[must_use] + pub const fn for_violations(violation_codes: Vec<&'static str>) -> Self { + Self { violation_codes } + } +} + /// Context used by the `sso.html` template #[derive(Serialize)] pub struct CompatSsoContext { diff --git a/crates/templates/src/lib.rs b/crates/templates/src/lib.rs index 32a41e8b2..dc0e1e714 100644 --- a/crates/templates/src/lib.rs +++ b/crates/templates/src/lib.rs @@ -37,14 +37,15 @@ mod macros; pub use self::{ context::{ - AccountInactiveContext, ApiDocContext, AppContext, CompatSsoContext, ConsentContext, - DeviceConsentContext, DeviceLinkContext, DeviceLinkFormField, DeviceNameContext, - EmailRecoveryContext, EmailVerificationContext, EmptyContext, ErrorContext, - FormPostContext, IndexContext, LoginContext, LoginFormField, NotFoundContext, - PasswordRegisterContext, PolicyViolationContext, PostAuthContext, PostAuthContextInner, - RecoveryExpiredContext, RecoveryFinishContext, RecoveryFinishFormField, - RecoveryProgressContext, RecoveryStartContext, RecoveryStartFormField, RegisterContext, - RegisterFormField, RegisterStepsDisplayNameContext, RegisterStepsDisplayNameFormField, + AccountInactiveContext, ApiDocContext, AppContext, CompatLoginPolicyViolationContext, + CompatSsoContext, ConsentContext, DeviceConsentContext, DeviceLinkContext, + DeviceLinkFormField, DeviceNameContext, EmailRecoveryContext, EmailVerificationContext, + EmptyContext, ErrorContext, FormPostContext, IndexContext, LoginContext, LoginFormField, + NotFoundContext, PasswordRegisterContext, PolicyViolationContext, PostAuthContext, + PostAuthContextInner, RecoveryExpiredContext, RecoveryFinishContext, + RecoveryFinishFormField, RecoveryProgressContext, RecoveryStartContext, + RecoveryStartFormField, RegisterContext, RegisterFormField, + RegisterStepsDisplayNameContext, RegisterStepsDisplayNameFormField, RegisterStepsEmailInUseContext, RegisterStepsRegistrationTokenContext, RegisterStepsRegistrationTokenFormField, RegisterStepsVerifyEmailContext, RegisterStepsVerifyEmailFormField, SiteBranding, SiteConfigExt, SiteFeatures, @@ -391,6 +392,9 @@ register_templates! { /// Render the policy violation page pub fn render_policy_violation(WithLanguage>>) { "pages/policy_violation.html" } + /// Render the compatibility login policy violation page + pub fn render_compat_login_policy_violation(WithLanguage>>) { "pages/compat_login_policy_violation.html" } + /// Render the legacy SSO login consent page pub fn render_sso_login(WithLanguage>>) { "pages/sso.html" } diff --git a/templates/pages/compat_login_policy_violation.html b/templates/pages/compat_login_policy_violation.html new file mode 100644 index 000000000..c4187336f --- /dev/null +++ b/templates/pages/compat_login_policy_violation.html @@ -0,0 +1,34 @@ +{# +Copyright 2024, 2025 New Vector Ltd. +Copyright 2022-2024 The Matrix.org Foundation C.I.C. + +SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial +Please see LICENSE files in the repository root for full details. +-#} + +{% extends "base.html" %} + +{% block content %} +
+
+ {{ icon.error_solid() }} +
+ +
+

{{ _("mas.policy_violation.heading") }}

+

{{ _("mas.policy_violation.description") }}

+
+
+ +
+
+

+ {{ _("mas.policy_violation.logged_as", username=current_session.user.username) }} +

+ + {{ logout.button(text=_("action.sign_out"), csrf_token=csrf_token, post_logout_action=action, as_link=True) }} +
+ + {{ _("action.cancel") }} +
+{% endblock content %} diff --git a/translations/en.json b/translations/en.json index cdf2df82d..af406ba66 100644 --- a/translations/en.json +++ b/translations/en.json @@ -6,7 +6,7 @@ }, "cancel": "Cancel", "@cancel": { - "context": "pages/consent.html:69:11-29, pages/device_consent.html:127:13-31, pages/policy_violation.html:44:13-31" + "context": "pages/compat_login_policy_violation.html:32:89-107, pages/consent.html:69:11-29, pages/device_consent.html:127:13-31, pages/policy_violation.html:44:13-31" }, "continue": "Continue", "@continue": { @@ -22,7 +22,7 @@ }, "sign_out": "Sign out", "@sign_out": { - "context": "pages/account/logged_out.html:22:28-48, pages/consent.html:65:28-48, pages/device_consent.html:136:30-50, pages/index.html:28:28-48, pages/policy_violation.html:38:28-48, pages/sso.html:45:28-48, pages/upstream_oauth2/link_mismatch.html:24:24-44, pages/upstream_oauth2/suggest_link.html:32:26-46" + "context": "pages/account/logged_out.html:22:28-48, pages/compat_login_policy_violation.html:29:28-48, pages/consent.html:65:28-48, pages/device_consent.html:136:30-50, pages/index.html:28:28-48, pages/policy_violation.html:38:28-48, pages/sso.html:45:28-48, pages/upstream_oauth2/link_mismatch.html:24:24-44, pages/upstream_oauth2/suggest_link.html:32:26-46" }, "skip": "Skip", "@skip": { @@ -496,17 +496,17 @@ "policy_violation": { "description": "This might be because of the client which authored the request, the currently logged in user, or the request itself.", "@description": { - "context": "pages/policy_violation.html:19:25-62", + "context": "pages/compat_login_policy_violation.html:19:25-62, pages/policy_violation.html:19:25-62", "description": "Displayed when an authorization request is denied by the policy" }, "heading": "The authorization request was denied by the policy enforced by this service", "@heading": { - "context": "pages/policy_violation.html:18:27-60", + "context": "pages/compat_login_policy_violation.html:18:27-60, pages/policy_violation.html:18:27-60", "description": "Displayed when an authorization request is denied by the policy" }, "logged_as": "Logged as %(username)s", "@logged_as": { - "context": "pages/policy_violation.html:35:11-86" + "context": "pages/compat_login_policy_violation.html:26:11-86, pages/policy_violation.html:35:11-86" } }, "recovery": {