aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cache.rs5
-rw-r--r--src/cache/font.rs4
-rw-r--r--src/cache/user.rs4
-rw-r--r--src/config.rs4
-rw-r--r--src/lib.rs5
-rw-r--r--src/main.rs2
-rw-r--r--src/theming.rs5
-rw-r--r--src/theming/hbs.rs6
-rw-r--r--src/theming/lua.rs45
9 files changed, 67 insertions, 13 deletions
diff --git a/src/cache.rs b/src/cache.rs
index 4ef77dc..0c254cb 100644
--- a/src/cache.rs
+++ b/src/cache.rs
@@ -82,3 +82,8 @@ where
pub type CacheFuture<Output> = Pin<Box<(dyn Future<Output = Result<Output, (StatusCode, &'static str)>> + Send + Sync)>>;
pub type CacheGetter<Output> = fn(&String) -> CacheFuture<Output>;
pub type Cache<Output> = Arc<RwLock<AsyncCache<String, Output, CacheGetter<Output>>>>;
+
+pub fn touch() {
+ user::touch();
+ font::touch();
+}
diff --git a/src/cache/font.rs b/src/cache/font.rs
index 5be2196..a238a87 100644
--- a/src/cache/font.rs
+++ b/src/cache/font.rs
@@ -57,3 +57,7 @@ static FONT_CACHE: LazyLock<FontCache> = LazyLock::new(|| {
pub async fn get_fontinfo(font: &String) -> Result<Arc<str>, (StatusCode, &'static str)> {
FONT_CACHE.write().await.get_owned(font).await
}
+
+pub fn touch() {
+ LazyLock::force(&FONT_CACHE);
+}
diff --git a/src/cache/user.rs b/src/cache/user.rs
index e228cc2..8d6bf64 100644
--- a/src/cache/user.rs
+++ b/src/cache/user.rs
@@ -101,3 +101,7 @@ pub async fn get_userinfo(user: &String) -> (Result<Arc<(User, Track, TrackStub)
}
}
}
+
+pub fn touch() {
+ LazyLock::force(&ALLOWLIST);
+}
diff --git a/src/config.rs b/src/config.rs
index 008eb7a..917646e 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -23,7 +23,7 @@ pub struct Config {
pub(crate) theme_dir: Option<Arc<str>>,
pub(crate) theme_ext_hbs: Arc<str>,
pub(crate) theme_ext_lua: Arc<str>,
- pub(crate) theme_debug: bool,
+ pub(crate) theme_dev: bool,
pub(crate) allowlist: BTreeSet<String>,
pub(crate) allowlist_mode: String,
@@ -48,7 +48,7 @@ impl Config {
theme_dir: var("LFME_THEME_DIR").ok().map(Into::into),
theme_ext_hbs: var("LFME_THEME_EXT_HBS").unwrap_or_else(|_| ".hbs".into()).into(),
theme_ext_lua: var("LFME_THEME_EXT_LUA").unwrap_or_else(|_| ".lua".into()).into(),
- theme_debug: var("LFME_THEME_DEV").map(|h| &h == "1").unwrap_or(false),
+ theme_dev: var("LFME_THEME_DEV").map(|h| &h == "1").unwrap_or(false),
allowlist: var("LFME_WHITELIST").or_else(|_| var("LFME_ALLOWLIST")).ok().map(|w| w.split(',').map(|s| s.trim().to_string()).collect()).unwrap_or_default(),
allowlist_mode: var("LFME_WHITELIST_MODE").or_else(|_| var("LFME_ALLOWLIST_MODE")).map(|m| m.to_ascii_lowercase()).unwrap_or_else(|_| "open".into()),
diff --git a/src/lib.rs b/src/lib.rs
index 1c2dea0..04fcdb7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -10,3 +10,8 @@ pub mod ctx;
pub mod theming;
pub use config::CONFIG;
+
+pub fn touch() {
+ cache::touch();
+ theming::touch();
+}
diff --git a/src/main.rs b/src/main.rs
index 57975db..6b1aac0 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -45,6 +45,8 @@ async fn main() {
.unwrap_or(env_logger::Target::Stderr)
).init();
+ lfm_embed::touch();
+
let user = warp::path!("user" / String)
.and(warp::query::<UserQuery>())
.then(|s, q: UserQuery| async move {
diff --git a/src/theming.rs b/src/theming.rs
index 1d7b1f2..6e5b3ba 100644
--- a/src/theming.rs
+++ b/src/theming.rs
@@ -24,3 +24,8 @@ pub fn render_theme(name: Option<&str>, ctx: &crate::ctx::Ctx) -> (String, Resul
(theme.into(), res)
}
+
+pub fn touch() {
+ hbs::touch();
+ lua::touch();
+}
diff --git a/src/theming/hbs.rs b/src/theming/hbs.rs
index 67a2ae4..398715a 100644
--- a/src/theming/hbs.rs
+++ b/src/theming/hbs.rs
@@ -18,7 +18,7 @@ static HANDLEBARS: LazyLock<Handlebars> = LazyLock::new(|| {
log::info!("Registering internal handlebars theme `{key}`");
hb.register_template_string(key, fulltext).unwrap();
}
- hb.set_dev_mode(CONFIG.theme_debug);
+ hb.set_dev_mode(CONFIG.theme_dev);
if let Some(themes_dir) = CONFIG.theme_dir.as_ref() {
log::info!("Registering handlebars theme dir `{themes_dir}` with extension `{}`.", CONFIG.theme_ext_hbs);
@@ -34,3 +34,7 @@ pub fn render_theme(name: &str, ctx: &crate::ctx::Ctx) -> Option<Result<String,
let render = templ.renders(&HANDLEBARS, &ctx, &mut RenderContext::new(Some(&name.into()))).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR);
Some(render)
}
+
+pub fn touch() {
+ LazyLock::force(&HANDLEBARS);
+}
diff --git a/src/theming/lua.rs b/src/theming/lua.rs
index 6bd6989..0699f09 100644
--- a/src/theming/lua.rs
+++ b/src/theming/lua.rs
@@ -18,7 +18,7 @@ static LUA: LazyLock<Mutex<Lua>> = LazyLock::new(|| {
lua.sandbox(true).expect("lua initialization");
lua.set_compiler(
- if CONFIG.theme_debug { Compiler::new().set_optimization_level(0).set_debug_level(2) }
+ if CONFIG.theme_dev { Compiler::new().set_optimization_level(0).set_debug_level(2) }
else { Compiler::new().set_optimization_level(2).set_debug_level(1) }
);
@@ -38,14 +38,19 @@ static LUA: LazyLock<Mutex<Lua>> = LazyLock::new(|| {
for (k, v) in INTERNAL_THEMES {
log::info!("Registering compiled lua theme `{k}`.");
- let _ = themes.set(*k, lua.load(*v).into_function().expect("loading internal theme"));
+ let _ = themes.set(*k, lua.load(*v).eval::<Value>().expect("loading internal theme"));
}
if let Some(theme_dir) = CONFIG.theme_dir.as_ref() {
- log::info!("Registering lua theme dir `{theme_dir}` with extension `{}`.", CONFIG.theme_ext_lua);
- for (k, v) in walk_dir(theme_dir.as_ref().as_ref()).expect("walking theme dir") {
- log::info!("Registering runtime lua theme `{k}`.");
- let _ = themes.set(k, lua.load(v).eval::<Value>().expect("loading internal theme"));
+ if !CONFIG.theme_dev {
+ log::info!("Registering lua theme dir `{theme_dir}` with extension `{}`.", CONFIG.theme_ext_lua);
+ for (k, v) in walk_dir(theme_dir.as_ref().as_ref()).expect("walking theme dir") {
+ log::info!("Registering runtime lua theme `{k}`.");
+ let _ = themes.set(k, lua.load(v).eval::<Value>().expect("loading external theme"));
+ }
+ }
+ else {
+ log::info!("Ready to dev-load lua themes from `{theme_dir}` with extension `{}`.", CONFIG.theme_ext_lua);
}
}
@@ -86,13 +91,29 @@ fn walk_dir(path: &Path) -> std::io::Result<Vec<(String, String)>> {
}
pub fn render_theme(name: &str, ctx: &crate::ctx::Ctx) -> Option<Result<String, StatusCode>> {
+ if name == ".." || name.starts_with("../") || name.ends_with("/..") || name.contains("/../") {
+ return Some(Err(StatusCode::BAD_REQUEST))
+ }
+
LUA.clear_poison();
let lua = LUA.lock().expect("FIXME: Mutex poisoning race condition.");
let themes: Table = lua.globals().get("__themes").unwrap();
- let Ok(Value::Function(theme)) = themes.get(name)
- else {
- return None;
- };
+ let theme;
+ match themes.get(name) {
+ Ok(Value::Function(themefn)) => { theme = themefn; },
+ Ok(Value::Nil) if !CONFIG.theme_dev || CONFIG.theme_dir.is_none() => { return None; },
+ Ok(Value::Nil) => {
+ let code = fs::read_to_string(CONFIG.theme_dir.as_ref().unwrap().to_string() + "/" + name + &CONFIG.theme_ext_lua).ok()?;
+ let res = lua.load(code).eval::<Value>();
+ match res {
+ Ok(Value::Function(themefn)) => { theme = themefn; },
+ Ok(v) => { log::error!("Got `{v:?}` instead of Function when dev-loading `{name}`."); return Some(Err(StatusCode::INTERNAL_SERVER_ERROR)); },
+ Err(e) => { log::error!("Error dev-loading `{name}`: {e}"); return Some(Err(StatusCode::INTERNAL_SERVER_ERROR)); },
+ }
+ },
+ Ok(v) => { log::error!("Got `{v:?}` instead of Function when loading `{name}`."); return Some(Err(StatusCode::INTERNAL_SERVER_ERROR)); }
+ Err(e) => { log::error!("Error loading `{name}`: {e}"); return Some(Err(StatusCode::INTERNAL_SERVER_ERROR)); }, //TODO: gate behind flag
+ }
let ctx = match lua.to_value(ctx) {
Ok(ok) => ok,
@@ -104,3 +125,7 @@ pub fn render_theme(name: &str, ctx: &crate::ctx::Ctx) -> Option<Result<String,
Some(theme.call((ctx,)).map_err(|e| { log::error!("Lua theme execution error: {e}"); StatusCode::INTERNAL_SERVER_ERROR }))
}
+
+pub fn touch() {
+ LazyLock::force(&LUA);
+}