diff --git a/Rocket.toml.dist b/Rocket.toml.dist index d861279..a0e2c91 100644 --- a/Rocket.toml.dist +++ b/Rocket.toml.dist @@ -15,6 +15,7 @@ keys_external_dir = "state/keys-external" token_dir = "state/tokens" tmp_dir = "state/tmp" mail_rate_limit = 60 +maintenance_file = "state/maintenance" [staging] base-URI = "https://keys.openpgp.org" @@ -29,6 +30,7 @@ assets_dir = "public/assets" token_dir = "tokens" tmp_dir = "tmp" mail_rate_limit = 60 +maintenance_file = "maintenance" [production] base-URI = "https://keys.openpgp.org" @@ -43,3 +45,4 @@ assets_dir = "public/assets" token_dir = "tokens" tmp_dir = "tmp" mail_rate_limit = 3600 +maintenance_file = "maintenance" diff --git a/dist/templates/maintenance.html.hbs b/dist/templates/maintenance.html.hbs new file mode 100644 index 0000000..1e7d895 --- /dev/null +++ b/dist/templates/maintenance.html.hbs @@ -0,0 +1,8 @@ +{{#> layout }} +
+ {{message}} +
+ +{{/layout}} diff --git a/src/web/maintenance.rs b/src/web/maintenance.rs new file mode 100644 index 0000000..1c1a16e --- /dev/null +++ b/src/web/maintenance.rs @@ -0,0 +1,68 @@ +use rocket::{Request, Data}; +use rocket::fairing::{Fairing, Info, Kind}; +use rocket_contrib::templates::Template; +use rocket::http::Method; + +use std::fs; +use std::path::PathBuf; + +use web::MyResponse; + +pub struct MaintenanceMode { + maintenance_file: PathBuf, +} + +mod templates { + #[derive(Serialize)] + pub struct MaintenanceMode { + pub message: String, + pub commit: String, + pub version: String, + } +} + +impl Fairing for MaintenanceMode { + fn info(&self) -> Info { + Info { + name: "Maintenance Mode", + kind: Kind::Request + } + } + + fn on_request(&self, request: &mut Request, _: &Data) { + if !self.is_relevant_path(request.uri().path()) { + return; + } + if let Some(message) = self.get_maintenance_message() { + request.set_uri(uri!(maintenance_error: message)); + request.set_method(Method::Get); + } + } +} + +impl MaintenanceMode { + pub fn new(maintenance_file: PathBuf) -> Self { + MaintenanceMode { maintenance_file } + } + + fn is_relevant_path(&self, path: &str) -> bool { + path.starts_with("/publish") || path.starts_with("/manage") + } + + fn get_maintenance_message(&self) -> Option