geforkt von mirrored/vaultwarden
Show organizations in admin panel, implement reload templates option
Dieser Commit ist enthalten in:
Ursprung
a797459560
Commit
bfd93e5b13
5 geänderte Dateien mit 56 neuen und 9 gelöschten Zeilen
|
@ -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
|
||||
|
|
|
@ -49,7 +49,7 @@ impl AdminTemplateData {
|
|||
}
|
||||
|
||||
fn render(self) -> Result<String, Error> {
|
||||
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<LoginForm>, mut cookies: Cookies, ip: ClientIp) -> Result<Redirect, Flash<Redirect>> {
|
||||
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(
|
||||
|
|
|
@ -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() {
|
||||
|
|
25
src/main.rs
25
src/main.rs
|
@ -331,9 +331,11 @@ pub struct Config {
|
|||
|
||||
mail: Option<MailConfig>,
|
||||
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<T: serde::ser::Serialize>(&self, name: &str, data: &T) -> Result<String, error::Error> {
|
||||
// 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),
|
||||
|
|
|
@ -7,12 +7,24 @@
|
|||
<div class="media pt-3">
|
||||
<img class="mr-2 rounded identicon" data-src="{{Email}}">
|
||||
<div class="media-body pb-3 mb-0 small border-bottom">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="row justify-content-between">
|
||||
<div class="col">
|
||||
<strong>{{Name}}</strong>
|
||||
<a class="tmp-del mr-3" href="" onclick='deleteUser("{{Id}}", "{{Email}}");'>Delete User</a>
|
||||
</div>
|
||||
<span class="d-block">{{Email}}</span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<strong> Organizations:</strong>
|
||||
<span class="d-block">
|
||||
{{#each Organizations}}
|
||||
<span class="badge badge-primary" data-orgtype="{{Type}}">{{Name}}</span>
|
||||
{{/each}}
|
||||
</span>
|
||||
</div>
|
||||
<div style="flex: 0 0 100px;">
|
||||
<a class="mr-3" href="" onclick='deleteUser("{{Id}}", "{{Email}}");'>Delete User</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/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;
|
||||
});
|
||||
});
|
||||
</script>
|
Laden …
In neuem Issue referenzieren