diff --git a/.env.template b/.env.template index ea3516bd..705e17b1 100644 --- a/.env.template +++ b/.env.template @@ -13,6 +13,8 @@ ## Templates data folder, by default uses embedded templates ## Check source code to see the format # TEMPLATES_FOLDER=/path/to/templates +## Automatically reload the templates for every request, slow, use only for development +# RELOAD_TEMPLATES=false ## Cache time-to-live for successfully obtained icons, in seconds (0 is "forever") # ICON_CACHE_TTL=2592000 diff --git a/src/api/admin.rs b/src/api/admin.rs index 18178d80..cb5edca7 100644 --- a/src/api/admin.rs +++ b/src/api/admin.rs @@ -49,7 +49,7 @@ impl AdminTemplateData { } fn render(self) -> Result { - CONFIG.templates.render("admin/base", &self).map_err(Into::into) + CONFIG.render_template("admin/base", &self) } } @@ -72,6 +72,7 @@ struct LoginForm { fn post_admin_login(data: Form, mut cookies: Cookies, ip: ClientIp) -> Result> { let data = data.into_inner(); + // If the token is invalid, redirect to login page if !_validate_token(&data.token) { error!("Invalid admin token. IP: {}", ip.ip); Err(Flash::error( diff --git a/src/mail.rs b/src/mail.rs index 6eddcc19..5246a261 100644 --- a/src/mail.rs +++ b/src/mail.rs @@ -36,7 +36,7 @@ fn mailer(config: &MailConfig) -> SmtpTransport { } fn get_text(template_name: &'static str, data: serde_json::Value) -> Result<(String, String), Error> { - let text = CONFIG.templates.render(template_name, &data)?; + let text = CONFIG.render_template(template_name, &data)?; let mut text_split = text.split(""); let subject = match text_split.next() { diff --git a/src/main.rs b/src/main.rs index 9861abc8..f78a7748 100644 --- a/src/main.rs +++ b/src/main.rs @@ -331,9 +331,11 @@ pub struct Config { mail: Option, templates: Handlebars, + templates_folder: String, + reload_templates: bool, } -fn load_templates(path: String) -> Handlebars { +fn load_templates(path: &str) -> Handlebars { let mut hb = Handlebars::new(); // Error on missing params hb.set_strict_mode(true); @@ -365,6 +367,21 @@ fn load_templates(path: String) -> Handlebars { } impl Config { + pub fn render_template(&self, name: &str, data: &T) -> Result { + // We add this to signal the compiler not to drop the result of 'load_templates' + let hb_owned; + + let hb = if CONFIG.reload_templates { + warn!("RELOADING TEMPLATES"); + hb_owned = load_templates(&self.templates_folder); + &hb_owned + } else { + &self.templates + }; + + hb.render(name, data).map_err(Into::into) + } + fn load() -> Self { use crate::util::{get_env, get_env_or}; dotenv::dotenv().ok(); @@ -377,11 +394,15 @@ impl Config { let yubico_client_id = get_env("YUBICO_CLIENT_ID"); let yubico_secret_key = get_env("YUBICO_SECRET_KEY"); + let templates_folder = get_env_or("TEMPLATES_FOLDER", format!("{}/{}", &df, "templates")); + Config { database_url: get_env_or("DATABASE_URL", format!("{}/{}", &df, "db.sqlite3")), icon_cache_folder: get_env_or("ICON_CACHE_FOLDER", format!("{}/{}", &df, "icon_cache")), attachments_folder: get_env_or("ATTACHMENTS_FOLDER", format!("{}/{}", &df, "attachments")), - templates: load_templates(get_env_or("TEMPLATES_FOLDER", format!("{}/{}", &df, "templates"))), + templates: load_templates(&templates_folder), + templates_folder, + reload_templates: get_env_or("RELOAD_TEMPLATES", false), // icon_cache_ttl defaults to 30 days (30 * 24 * 60 * 60 seconds) icon_cache_ttl: get_env_or("ICON_CACHE_TTL", 2_592_000), diff --git a/src/static/templates/admin/page.hbs b/src/static/templates/admin/page.hbs index 4b55cea3..7ee748b6 100644 --- a/src/static/templates/admin/page.hbs +++ b/src/static/templates/admin/page.hbs @@ -7,11 +7,23 @@
-
- {{Name}} - Delete User +
+
+ {{Name}} + {{Email}} +
+
+ Organizations: + + {{#each Organizations}} + {{Name}} + {{/each}} + +
+
- {{Email}}
{{/each}} @@ -73,11 +85,22 @@ "Error inviting user", data); } + let OrgTypes = { + "0": { "name": "Owner", "color": "orange" }, + "1": { "name": "Admin", "color": "blueviolet" }, + "2": { "name": "User", "color": "blue" }, + "3": { "name": "Manager", "color": "green" }, + }; + $(window).on('load', function () { - //$("#reload-btn").click(reload); $("#invite-form").submit(inviteUser); $("img.identicon").each(function (i, e) { e.src = identicon(e.dataset.src); }); + $('[data-orgtype]').each(function (i, e) { + let orgtype = OrgTypes[e.dataset.orgtype]; + e.style.backgroundColor = orgtype.color; + e.title = orgtype.name; + }); }); \ No newline at end of file