]> git.proxmox.com Git - proxmox-backup.git/commitdiff
change index to templates using handlebars
authorDominik Csapak <d.csapak@proxmox.com>
Wed, 29 Apr 2020 09:59:31 +0000 (11:59 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Wed, 29 Apr 2020 15:05:53 +0000 (17:05 +0200)
using a handlebars instance in ApiConfig, to cache the templates
as long as possible, this is currently ok, as the index template
can only change when the whole package changes

if we split this in the future, we have to trigger a reload of
the daemon on gui package upgrade (so that the template gets reloaded)

Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
Cargo.toml
debian/proxmox-backup-server.install
src/bin/proxmox-backup-api.rs
src/bin/proxmox-backup-proxy.rs
src/server/config.rs
src/server/rest.rs
www/Makefile
www/index.hbs [new file with mode: 0644]

index 2df47e9b0bf11a931e432dc3c5b3b23831e5ec9b..a155c8728909c329439bfde5ce31d3d44301ac91 100644 (file)
@@ -22,6 +22,7 @@ endian_trait = { version = "0.6", features = ["arrays"] }
 anyhow = "1.0"
 futures = "0.3"
 h2 = { version = "0.2", features = ["stream"] }
+handlebars = "3.0"
 http = "0.2"
 hyper = "0.13"
 lazy_static = "1.4"
index fe3ba602a6ccbd4af63add611957d6a0ef363ea9..2704228d11e3dde6c086eb1ecf0d0b5e156cf91f 100644 (file)
@@ -5,6 +5,7 @@ usr/lib/x86_64-linux-gnu/proxmox-backup/proxmox-backup-api
 usr/lib/x86_64-linux-gnu/proxmox-backup/proxmox-backup-proxy
 usr/lib/x86_64-linux-gnu/proxmox-backup/proxmox-backup-banner
 usr/sbin/proxmox-backup-manager
+usr/share/javascript/proxmox-backup/index.hbs
 usr/share/javascript/proxmox-backup/css/ext6-pbs.css
 usr/share/javascript/proxmox-backup/images/logo-128.png
 usr/share/javascript/proxmox-backup/images/proxmox_logo.png
index f5e8bbe6e106378eaa6dfc9eed24b5129a297fd7..892ae58b932aa9de515f9321262ef4a1cb05915b 100644 (file)
@@ -45,7 +45,7 @@ async fn run() -> Result<(), Error> {
     let _ = csrf_secret(); // load with lazy_static
 
     let config = server::ApiConfig::new(
-        buildcfg::JS_DIR, &proxmox_backup::api2::ROUTER, RpcEnvironmentType::PRIVILEGED);
+        buildcfg::JS_DIR, &proxmox_backup::api2::ROUTER, RpcEnvironmentType::PRIVILEGED)?;
  
     let rest_server = RestServer::new(config);
 
index f1612e6957c15eb0db8814672622baa5220c3e7a..ef6e670347b2617889b721cd25ce919044496830 100644 (file)
@@ -34,7 +34,7 @@ async fn run() -> Result<(), Error> {
     let _ = csrf_secret(); // load with lazy_static
 
     let mut config = ApiConfig::new(
-        buildcfg::JS_DIR, &proxmox_backup::api2::ROUTER, RpcEnvironmentType::PUBLIC);
+        buildcfg::JS_DIR, &proxmox_backup::api2::ROUTER, RpcEnvironmentType::PUBLIC)?;
 
     // add default dirs which includes jquery and bootstrap
     // my $base = '/usr/share/libpve-http-server-perl';
index d9aa076c40eef5d22685db853fa29c9b9f0cbbbc..e8b3c94653811baf1e1f01b87c65641e7c1741c3 100644 (file)
@@ -1,7 +1,9 @@
 use std::collections::HashMap;
 use std::path::{PathBuf};
+use anyhow::Error;
 
 use hyper::Method;
+use handlebars::Handlebars;
 
 use proxmox::api::{ApiMethod, Router, RpcEnvironmentType};
 
@@ -10,17 +12,22 @@ pub struct ApiConfig {
     router: &'static Router,
     aliases: HashMap<String, PathBuf>,
     env_type: RpcEnvironmentType,
+    pub templates: Handlebars<'static>,
 }
 
 impl ApiConfig {
 
-    pub fn new<B: Into<PathBuf>>(basedir: B, router: &'static Router, env_type: RpcEnvironmentType) -> Self {
-        Self {
-            basedir: basedir.into(),
+    pub fn new<B: Into<PathBuf>>(basedir: B, router: &'static Router, env_type: RpcEnvironmentType) -> Result<Self, Error> {
+        let mut templates = Handlebars::new();
+        let basedir = basedir.into();
+        templates.register_template_file("index", basedir.join("index.hbs"))?;
+        Ok(Self {
+            basedir,
             router,
             aliases: HashMap::new(),
             env_type,
-        }
+            templates
+        })
     }
 
     pub fn find_method(
index f648af3acd5c79981c4a0b8226dca1dd35f1b1ee..95f731913a10bb86477b87261e5e3d1f94bcf009 100644 (file)
@@ -16,6 +16,7 @@ use serde_json::{json, Value};
 use tokio::fs::File;
 use tokio::time::Instant;
 use url::form_urlencoded;
+use handlebars::Handlebars;
 
 use proxmox::http_err;
 use proxmox::api::{ApiHandler, ApiMethod, HttpError};
@@ -311,59 +312,43 @@ pub async fn handle_api_request<Env: RpcEnvironment, S: 'static + BuildHasher +
     Ok(resp)
 }
 
-fn get_index(username: Option<String>, token: Option<String>) ->  Response<Body> {
+fn get_index(username: Option<String>, token: Option<String>, template: &Handlebars, parts: Parts) ->  Response<Body> {
 
     let nodename = proxmox::tools::nodename();
     let username = username.unwrap_or_else(|| String::from(""));
 
     let token = token.unwrap_or_else(|| String::from(""));
 
-    let setup = json!({
-        "Setup": { "auth_cookie_name": "PBSAuthCookie" },
+    let mut debug = false;
+
+    if let Some(query_str) = parts.uri.query() {
+        for (k, v) in form_urlencoded::parse(query_str.as_bytes()).into_owned() {
+            if k == "debug" && v == "1" || v == "true" {
+                debug = true;
+            }
+        }
+    }
+
+    let data = json!({
         "NodeName": nodename,
         "UserName": username,
         "CSRFPreventionToken": token,
+        "debug": debug,
     });
 
-    let index = format!(r###"
-<!DOCTYPE html>
-<html>
-  <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-    <meta http-equiv="X-UA-Compatible" content="IE=edge">
-    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
-    <title>Proxmox Backup Server</title>
-    <link rel="icon" sizes="128x128" href="/images/logo-128.png" />
-    <link rel="apple-touch-icon" sizes="128x128" href="/pve2/images/logo-128.png" />
-    <link rel="stylesheet" type="text/css" href="/extjs/theme-crisp/resources/theme-crisp-all.css" />
-    <link rel="stylesheet" type="text/css" href="/extjs/crisp/resources/charts-all.css" />
-    <link rel="stylesheet" type="text/css" href="/fontawesome/css/font-awesome.css" />
-    <link rel="stylesheet" type="text/css" href="/css/ext6-pbs.css" />
-    <script type='text/javascript'> function gettext(buf) {{ return buf; }} </script>
-    <script type="text/javascript" src="/extjs/ext-all-debug.js"></script>
-    <script type="text/javascript" src="/extjs/charts-debug.js"></script>
-    <script type="text/javascript">
-      Proxmox = {};
-    </script>
-    <script type="text/javascript" src="/widgettoolkit/proxmoxlib.js"></script>
-    <script type="text/javascript" src="/extjs/locale/locale-en.js"></script>
-    <script type="text/javascript">
-      Ext.History.fieldid = 'x-history-field';
-    </script>
-    <script type="text/javascript" src="/js/proxmox-backup-gui.js"></script>
-  </head>
-  <body>
-    <!-- Fields required for history management -->
-    <form id="history-form" class="x-hidden">
-      <input type="hidden" id="x-history-field"/>
-    </form>
-  </body>
-</html>
-"###, setup.to_string());
+    let mut ct = "text/html";
+
+    let index = match template.render("index", &data) {
+        Ok(index) => index,
+        Err(err) => {
+            ct = "text/plain";
+            format!("Error rendering template: {}", err.desc)
+        },
+    };
 
     Response::builder()
         .status(StatusCode::OK)
-        .header(header::CONTENT_TYPE, "text/html")
+        .header(header::CONTENT_TYPE, ct)
         .body(index.into())
         .unwrap()
 }
@@ -595,15 +580,15 @@ pub async fn handle_request(api: Arc<ApiConfig>, req: Request<Body>) -> Result<R
                 match check_auth(&method, &ticket, &token, &user_info) {
                     Ok(username) => {
                         let new_token = assemble_csrf_prevention_token(csrf_secret(), &username);
-                        return Ok(get_index(Some(username), Some(new_token)));
+                        return Ok(get_index(Some(username), Some(new_token), &api.templates, parts));
                     }
                     _ => {
                         tokio::time::delay_until(Instant::from_std(delay_unauth_time)).await;
-                        return Ok(get_index(None, None));
+                        return Ok(get_index(None, None, &api.templates, parts));
                     }
                 }
             } else {
-                return Ok(get_index(None, None));
+                return Ok(get_index(None, None, &api.templates, parts));
             }
         } else {
             let filename = api.find_alias(&components);
index ef7c7300da73cc326d5244d5982a835d7be022c3..461b55229ab5ef6075676cd78e0c8b5feaaa9a13 100644 (file)
@@ -36,8 +36,9 @@ clean:
        find . -name '*~' -exec rm {} ';'       
        rm -rf js
 
-install: js/proxmox-backup-gui.js css/ext6-pbs.css
+install: js/proxmox-backup-gui.js css/ext6-pbs.css index.hbs
        install -dm755 $(DESTDIR)$(JSDIR)
+       install -m644 index.hbs $(DESTDIR)$(JSDIR)/
        install -dm755 $(DESTDIR)$(JSDIR)/js
        install -m644 js/proxmox-backup-gui.js $(DESTDIR)$(JSDIR)/js/
        install -dm755 $(DESTDIR)$(JSDIR)/css
diff --git a/www/index.hbs b/www/index.hbs
new file mode 100644 (file)
index 0000000..9ede764
--- /dev/null
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
+    <title>Proxmox Backup Server</title>
+    <link rel="icon" sizes="128x128" href="/images/logo-128.png" />
+    <link rel="apple-touch-icon" sizes="128x128" href="/pve2/images/logo-128.png" />
+    <link rel="stylesheet" type="text/css" href="/extjs/theme-crisp/resources/theme-crisp-all.css" />
+    <link rel="stylesheet" type="text/css" href="/extjs/crisp/resources/charts-all.css" />
+    <link rel="stylesheet" type="text/css" href="/fontawesome/css/font-awesome.css" />
+    <link rel="stylesheet" type="text/css" href="/css/ext6-pbs.css" />
+    <script type='text/javascript'> function gettext(buf) { return buf; } </script>
+    {{#if debug}}
+    <script type="text/javascript" src="/extjs/ext-all-debug.js"></script>
+    <script type="text/javascript" src="/extjs/charts-debug.js"></script>
+    {{else}}
+    <script type="text/javascript" src="/extjs/ext-all.js"></script>
+    <script type="text/javascript" src="/extjs/charts.js"></script>
+    {{/if}}
+    <script type="text/javascript">
+    Proxmox = {
+       Setup: { auth_cookie_name: 'PBSAuthCookie' },
+       NodeName: "{{ NodeName }}",
+       UserName: "{{ UserName }}",
+       CSRFPreventionToken: "{{ CSRFPreventionToken }}",
+    };
+    </script>
+    <script type="text/javascript" src="/widgettoolkit/proxmoxlib.js"></script>
+    <script type="text/javascript" src="/extjs/locale/locale-en.js"></script>
+    <script type="text/javascript">
+      Ext.History.fieldid = 'x-history-field';
+    </script>
+    <script type="text/javascript" src="/js/proxmox-backup-gui.js"></script>
+  </head>
+  <body>
+    <!-- Fields required for history management -->
+    <form id="history-form" class="x-hidden">
+      <input type="hidden" id="x-history-field"/>
+    </form>
+  </body>
+</html>