1
0
Fork 1
Spiegel von https://github.com/dani-garcia/vaultwarden.git synchronisiert 2024-11-25 05:40:29 +01:00

Show organizations in admin panel, implement reload templates option

Dieser Commit ist enthalten in:
Daniel García 2019-01-20 17:43:56 +01:00
Ursprung a797459560
Commit bfd93e5b13
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: FC8A7D14C3CD543A
5 geänderte Dateien mit 56 neuen und 9 gelöschten Zeilen

Datei anzeigen

@ -13,6 +13,8 @@
## Templates data folder, by default uses embedded templates ## Templates data folder, by default uses embedded templates
## Check source code to see the format ## Check source code to see the format
# TEMPLATES_FOLDER=/path/to/templates # 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") ## Cache time-to-live for successfully obtained icons, in seconds (0 is "forever")
# ICON_CACHE_TTL=2592000 # ICON_CACHE_TTL=2592000

Datei anzeigen

@ -49,7 +49,7 @@ impl AdminTemplateData {
} }
fn render(self) -> Result<String, Error> { 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>> { fn post_admin_login(data: Form<LoginForm>, mut cookies: Cookies, ip: ClientIp) -> Result<Redirect, Flash<Redirect>> {
let data = data.into_inner(); let data = data.into_inner();
// If the token is invalid, redirect to login page
if !_validate_token(&data.token) { if !_validate_token(&data.token) {
error!("Invalid admin token. IP: {}", ip.ip); error!("Invalid admin token. IP: {}", ip.ip);
Err(Flash::error( Err(Flash::error(

Datei anzeigen

@ -36,7 +36,7 @@ fn mailer(config: &MailConfig) -> SmtpTransport {
} }
fn get_text(template_name: &'static str, data: serde_json::Value) -> Result<(String, String), Error> { 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 mut text_split = text.split("<!---------------->");
let subject = match text_split.next() { let subject = match text_split.next() {

Datei anzeigen

@ -331,9 +331,11 @@ pub struct Config {
mail: Option<MailConfig>, mail: Option<MailConfig>,
templates: Handlebars, 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(); let mut hb = Handlebars::new();
// Error on missing params // Error on missing params
hb.set_strict_mode(true); hb.set_strict_mode(true);
@ -365,6 +367,21 @@ fn load_templates(path: String) -> Handlebars {
} }
impl Config { 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 { fn load() -> Self {
use crate::util::{get_env, get_env_or}; use crate::util::{get_env, get_env_or};
dotenv::dotenv().ok(); dotenv::dotenv().ok();
@ -377,11 +394,15 @@ impl Config {
let yubico_client_id = get_env("YUBICO_CLIENT_ID"); let yubico_client_id = get_env("YUBICO_CLIENT_ID");
let yubico_secret_key = get_env("YUBICO_SECRET_KEY"); let yubico_secret_key = get_env("YUBICO_SECRET_KEY");
let templates_folder = get_env_or("TEMPLATES_FOLDER", format!("{}/{}", &df, "templates"));
Config { Config {
database_url: get_env_or("DATABASE_URL", format!("{}/{}", &df, "db.sqlite3")), database_url: get_env_or("DATABASE_URL", format!("{}/{}", &df, "db.sqlite3")),
icon_cache_folder: get_env_or("ICON_CACHE_FOLDER", format!("{}/{}", &df, "icon_cache")), icon_cache_folder: get_env_or("ICON_CACHE_FOLDER", format!("{}/{}", &df, "icon_cache")),
attachments_folder: get_env_or("ATTACHMENTS_FOLDER", format!("{}/{}", &df, "attachments")), 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 defaults to 30 days (30 * 24 * 60 * 60 seconds)
icon_cache_ttl: get_env_or("ICON_CACHE_TTL", 2_592_000), icon_cache_ttl: get_env_or("ICON_CACHE_TTL", 2_592_000),

Datei anzeigen

@ -7,11 +7,23 @@
<div class="media pt-3"> <div class="media pt-3">
<img class="mr-2 rounded identicon" data-src="{{Email}}"> <img class="mr-2 rounded identicon" data-src="{{Email}}">
<div class="media-body pb-3 mb-0 small border-bottom"> <div class="media-body pb-3 mb-0 small border-bottom">
<div class="d-flex justify-content-between"> <div class="row justify-content-between">
<strong>{{Name}}</strong> <div class="col">
<a class="tmp-del mr-3" href="" onclick='deleteUser("{{Id}}", "{{Email}}");'>Delete User</a> <strong>{{Name}}</strong>
<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>
<span class="d-block">{{Email}}</span>
</div> </div>
</div> </div>
{{/each}} {{/each}}
@ -73,11 +85,22 @@
"Error inviting user", data); "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 () { $(window).on('load', function () {
//$("#reload-btn").click(reload);
$("#invite-form").submit(inviteUser); $("#invite-form").submit(inviteUser);
$("img.identicon").each(function (i, e) { $("img.identicon").each(function (i, e) {
e.src = identicon(e.dataset.src); 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> </script>