allowthem_server/
browser_templates.rs1use std::sync::Arc;
2
3use axum::response::Html;
4use minijinja::Environment;
5
6use crate::browser_error::BrowserError;
7
8const BASE_HTML: &str = include_str!("templates/base.html");
9const LOGIN_HTML: &str = include_str!("templates/login.html");
10const REGISTER_HTML: &str = include_str!("templates/register.html");
11const SETTINGS_HTML: &str = include_str!("templates/settings.html");
12const CONSENT_HTML: &str = include_str!("templates/consent.html");
13const FORGOT_PASSWORD_HTML: &str = include_str!("templates/forgot_password.html");
14const RESET_PASSWORD_HTML: &str = include_str!("templates/reset_password.html");
15const MFA_SETUP_HTML: &str = include_str!("templates/mfa_setup.html");
16const MFA_RECOVERY_HTML: &str = include_str!("templates/mfa_recovery.html");
17const MFA_CHALLENGE_HTML: &str = include_str!("templates/mfa_challenge.html");
18const MODELINE_PARTIAL: &str = include_str!("templates/_partials/_modeline.html");
19const FLASH_PARTIAL: &str = include_str!("templates/_partials/_flash.html");
20const SPLASH_PARTIAL: &str = include_str!("templates/_partials/_splash.html");
21const AUTH_SHELL_PARTIAL: &str = include_str!("templates/_partials/_auth_shell.html");
22const APP_SHELL_PARTIAL: &str = include_str!("templates/_partials/_app_shell.html");
23const SIDEBAR_NAV_PARTIAL: &str = include_str!("templates/_partials/_sidebar_nav.html");
24const AUTH_MACROS_PARTIAL: &str = include_str!("templates/_partials/_auth_macros.html");
25const AUTH_OOB_HEAD_PARTIAL: &str = include_str!("templates/_partials/_auth_oob_head.html");
26const AUTH_MAIN_LOGIN_PARTIAL: &str = include_str!("templates/_partials/_auth_main_login.html");
27const AUTH_MAIN_REGISTER_PARTIAL: &str =
28 include_str!("templates/_partials/_auth_main_register.html");
29const AUTH_MAIN_FORGOT_PW_PARTIAL: &str =
30 include_str!("templates/_partials/_auth_main_forgot_password.html");
31const AUTH_MAIN_RESET_PW_PARTIAL: &str =
32 include_str!("templates/_partials/_auth_main_reset_password.html");
33const AUTH_MAIN_MFA_CHALLENGE_PARTIAL: &str =
34 include_str!("templates/_partials/_auth_main_mfa_challenge.html");
35const AUTH_MAIN_MFA_SETUP_PARTIAL: &str =
36 include_str!("templates/_partials/_auth_main_mfa_setup.html");
37const AUTH_MAIN_MFA_RECOVERY_PARTIAL: &str =
38 include_str!("templates/_partials/_auth_main_mfa_recovery.html");
39const AUTH_MAIN_CONSENT_PARTIAL: &str =
40 include_str!("templates/_partials/_auth_main_consent.html");
41
42pub fn add_default_browser_templates(env: &mut Environment<'static>) {
95 env.add_template_owned("base.html", BASE_HTML)
96 .expect("base.html");
97 env.add_template_owned("login.html", LOGIN_HTML)
98 .expect("login.html");
99 env.add_template_owned("register.html", REGISTER_HTML)
100 .expect("register.html");
101 env.add_template_owned("settings.html", SETTINGS_HTML)
102 .expect("settings.html");
103 env.add_template_owned("consent.html", CONSENT_HTML)
104 .expect("consent.html");
105 env.add_template_owned("forgot_password.html", FORGOT_PASSWORD_HTML)
106 .expect("forgot_password.html");
107 env.add_template_owned("reset_password.html", RESET_PASSWORD_HTML)
108 .expect("reset_password.html");
109 env.add_template_owned("mfa_setup.html", MFA_SETUP_HTML)
110 .expect("mfa_setup.html");
111 env.add_template_owned("mfa_recovery.html", MFA_RECOVERY_HTML)
112 .expect("mfa_recovery.html");
113 env.add_template_owned("mfa_challenge.html", MFA_CHALLENGE_HTML)
114 .expect("mfa_challenge.html");
115 env.add_template_owned("_partials/_modeline.html", MODELINE_PARTIAL)
116 .expect("_partials/_modeline.html");
117 env.add_template_owned("_partials/_flash.html", FLASH_PARTIAL)
118 .expect("_partials/_flash.html");
119 env.add_template_owned("_partials/_splash.html", SPLASH_PARTIAL)
120 .expect("_partials/_splash.html");
121 env.add_template_owned("_partials/_auth_shell.html", AUTH_SHELL_PARTIAL)
122 .expect("_partials/_auth_shell.html");
123 env.add_template_owned("_partials/_app_shell.html", APP_SHELL_PARTIAL)
124 .expect("_partials/_app_shell.html");
125 env.add_template_owned("_partials/_sidebar_nav.html", SIDEBAR_NAV_PARTIAL)
126 .expect("_partials/_sidebar_nav.html");
127 env.add_template_owned("_partials/_auth_macros.html", AUTH_MACROS_PARTIAL)
128 .expect("_partials/_auth_macros.html");
129 env.add_template_owned("_partials/_auth_oob_head.html", AUTH_OOB_HEAD_PARTIAL)
130 .expect("_partials/_auth_oob_head.html");
131 env.add_template_owned("_partials/_auth_main_login.html", AUTH_MAIN_LOGIN_PARTIAL)
132 .expect("_partials/_auth_main_login.html");
133 env.add_template_owned(
134 "_partials/_auth_main_register.html",
135 AUTH_MAIN_REGISTER_PARTIAL,
136 )
137 .expect("_partials/_auth_main_register.html");
138 env.add_template_owned(
139 "_partials/_auth_main_forgot_password.html",
140 AUTH_MAIN_FORGOT_PW_PARTIAL,
141 )
142 .expect("_partials/_auth_main_forgot_password.html");
143 env.add_template_owned(
144 "_partials/_auth_main_reset_password.html",
145 AUTH_MAIN_RESET_PW_PARTIAL,
146 )
147 .expect("_partials/_auth_main_reset_password.html");
148 env.add_template_owned(
149 "_partials/_auth_main_mfa_challenge.html",
150 AUTH_MAIN_MFA_CHALLENGE_PARTIAL,
151 )
152 .expect("_partials/_auth_main_mfa_challenge.html");
153 env.add_template_owned(
154 "_partials/_auth_main_mfa_setup.html",
155 AUTH_MAIN_MFA_SETUP_PARTIAL,
156 )
157 .expect("_partials/_auth_main_mfa_setup.html");
158 env.add_template_owned(
159 "_partials/_auth_main_mfa_recovery.html",
160 AUTH_MAIN_MFA_RECOVERY_PARTIAL,
161 )
162 .expect("_partials/_auth_main_mfa_recovery.html");
163 env.add_template_owned(
164 "_partials/_auth_main_consent.html",
165 AUTH_MAIN_CONSENT_PARTIAL,
166 )
167 .expect("_partials/_auth_main_consent.html");
168}
169
170pub fn build_default_browser_env() -> Arc<Environment<'static>> {
171 let mut env = Environment::new();
172 add_default_browser_templates(&mut env);
173 Arc::new(env)
174}
175
176pub fn render(
177 env: &Environment<'_>,
178 template_name: &str,
179 ctx: minijinja::value::Value,
180) -> Result<Html<String>, BrowserError> {
181 let tmpl = env.get_template(template_name)?;
182 let rendered = tmpl.render(ctx)?;
183 Ok(Html(rendered))
184}
185
186#[cfg(test)]
187mod tests {
188 use super::*;
189
190 #[test]
191 fn default_env_loads_all_browser_templates() {
192 let env = build_default_browser_env();
193 for name in [
194 "base.html",
195 "login.html",
196 "register.html",
197 "settings.html",
198 "consent.html",
199 "forgot_password.html",
200 "reset_password.html",
201 "mfa_setup.html",
202 "mfa_recovery.html",
203 "mfa_challenge.html",
204 "_partials/_modeline.html",
205 "_partials/_flash.html",
206 "_partials/_splash.html",
207 "_partials/_auth_shell.html",
208 "_partials/_app_shell.html",
209 "_partials/_sidebar_nav.html",
210 "_partials/_auth_macros.html",
211 "_partials/_auth_oob_head.html",
212 "_partials/_auth_main_login.html",
213 "_partials/_auth_main_register.html",
214 "_partials/_auth_main_forgot_password.html",
215 "_partials/_auth_main_reset_password.html",
216 "_partials/_auth_main_mfa_challenge.html",
217 "_partials/_auth_main_mfa_setup.html",
218 "_partials/_auth_main_mfa_recovery.html",
219 "_partials/_auth_main_consent.html",
220 ] {
221 assert!(
222 env.get_template(name).is_ok(),
223 "template {name} should be loadable"
224 );
225 }
226 }
227
228 #[test]
229 fn render_produces_html() {
230 let env = build_default_browser_env();
231 let result = render(
232 &env,
233 "login.html",
234 minijinja::context! {
235 csrf_token => "test",
236 is_production => false,
237 },
238 );
239 assert!(result.is_ok());
240 }
241}