Skip to main content

laterite_web/theme/
maintenance.rs

1//! Maintenance mode: the site answers every visitor with the theme's
2//! `/maintenance` page, or a plain notice, with status 503, while an operator
3//! with the themes permission still sees the site.
4
5use laterite_admin::form::FormField;
6use laterite_admin::settings::{SettingsItem, SettingsModel};
7use laterite_admin::{Permission, ROLE_ADMIN};
8use laterite_core::t;
9use serde::{Deserialize, Serialize};
10
11/// The permission to switch maintenance mode.
12pub const PERMISSION: &str = "web.manage_site";
13
14/// The setting, under Settings › Website.
15#[derive(Debug, Clone, Default, Serialize, Deserialize)]
16#[serde(default)]
17pub struct MaintenanceSettings {
18    pub enabled: bool,
19    /// Shown by the plain notice when the theme has no `/maintenance` page.
20    pub message: String,
21}
22
23impl SettingsModel for MaintenanceSettings {
24    const CODE: &'static str = "web.maintenance";
25}
26
27/// The permission, as the module registers it.
28pub fn permission() -> Permission {
29    Permission::new(PERMISSION, t!("Manage the site"), t!("Website")).roles([ROLE_ADMIN])
30}
31
32/// The settings screen, as the module registers it.
33pub fn settings_item() -> SettingsItem {
34    SettingsItem::new(
35        MaintenanceSettings::CODE,
36        t!("Maintenance mode"),
37        vec![
38            FormField::switch("enabled", t!("Show visitors the maintenance page")),
39            FormField::textarea("message", t!("Message")).help(t!(
40                "Shown when the theme has no page at /maintenance. Operators who may manage themes still see the site."
41            )),
42        ],
43    )
44    .description(t!("Take the site down for visitors while you work on it."))
45    .category(t!("Website"))
46    .slot(laterite_core::arrange::slot::CONTENT)
47    .order(20)
48    .icon("wrench")
49    .permission(PERMISSION)
50}
51
52/// The plain notice, when the theme has no `/maintenance` page.
53pub fn notice(message: &str) -> String {
54    let text = if message.trim().is_empty() {
55        "This site is down for maintenance. Please come back soon."
56    } else {
57        message.trim()
58    };
59    format!(
60        "<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"robots\" content=\"noindex\"><title>Maintenance</title></head><body><main><p>{}</p></main></body></html>",
61        crate::escape(text)
62    )
63}