diff --git a/flake.nix b/flake.nix index ece7d09..f6fdb6f 100644 --- a/flake.nix +++ b/flake.nix @@ -42,7 +42,8 @@ buildInputs = [ pkgs.makeWrapper ]; postBuild = '' wrapProgram $out/bin/${name} \ - --set TRANSBEAM_STATIC_DIR ${./static} + --set TRANSBEAM_STATIC_DIR ${./static} \ + --set TRANSBEAM_CACHEBUSTER ${builtins.substring 0 8 (builtins.hashString "sha256" (toString ./static))} ''; }; diff --git a/src/main.rs b/src/main.rs index 2fa3456..76ff8d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,9 +6,8 @@ mod zip; use std::{fmt::Debug, path::PathBuf, str::FromStr}; -use actix_files::NamedFile; use actix_web::{ - error::InternalError, get, http::StatusCode, middleware::Logger, post, web, App, HttpRequest, + error::InternalError, get, middleware::Logger, post, web, App, HttpRequest, HttpResponse, HttpServer, Responder, }; use actix_web_actors::ws; @@ -31,9 +30,9 @@ struct Config { max_lifetime: u16, upload_password: String, storage_dir: PathBuf, - static_dir: PathBuf, reverse_proxy: bool, mnemonic_codes: bool, + cachebuster: String, } pub fn get_ip_addr(req: &HttpRequest, reverse_proxy: bool) -> String { @@ -51,14 +50,29 @@ pub fn log_auth_failure(ip_addr: &str) { warn!("Incorrect authentication attempt from {}", ip_addr); } +#[derive(Template)] +#[template(path = "index.html")] +struct IndexPage<'a> { cachebuster: &'a str } + +#[get("/")] +async fn index(data: web::Data) -> impl Responder { + HttpResponse::Ok().body(IndexPage { cachebuster: &data.config.cachebuster }.render().unwrap()) +} + #[derive(Deserialize)] struct DownloadRequest { code: String, download: Option, } -#[derive(Serialize, Template)] +#[derive(Template)] #[template(path = "download.html")] +struct DownloadPage<'a> { + info: DownloadInfo, + cachebuster: &'a str, +} + +#[derive(Serialize)] struct DownloadInfo { file: StoredFile, code: String, @@ -105,11 +119,14 @@ async fn handle_download( } else { let offsets = info.contents.as_deref().map(zip::file_data_offsets); Ok(HttpResponse::Ok().body( - DownloadInfo { - file: info, - code: code.clone(), - available: file.metadata().await?.len(), - offsets, + DownloadPage { + info: DownloadInfo { + file: info, + code: code.clone(), + available: file.metadata().await?.len(), + offsets, + }, + cachebuster: &data.config.cachebuster, } .render() .unwrap(), @@ -149,6 +166,10 @@ async fn download_info( })) } +#[derive(Template)] +#[template(path = "404.html")] +struct NotFoundPage<'a> { cachebuster: &'a str } + fn not_found(req: HttpRequest, data: web::Data, report: bool) -> actix_web::Result { if report { let ip_addr = get_ip_addr(&req, data.config.reverse_proxy); @@ -156,9 +177,7 @@ fn not_found(req: HttpRequest, data: web::Data, report: bool) -> ac } Err(InternalError::from_response( "Download not found", - NamedFile::open(data.config.static_dir.join("404.html"))? - .set_status_code(StatusCode::NOT_FOUND) - .into_response(&req), + HttpResponse::NotFound().body(NotFoundPage { cachebuster: &data.config.cachebuster }.render().unwrap()), ) .into()) } @@ -258,6 +277,7 @@ async fn main() -> std::io::Result<()> { env_or::("TRANSBEAM_MAX_STORAGE_SIZE", ByteSize(64 * bytesize::GB)).as_u64(); let upload_password: String = std::env::var("TRANSBEAM_UPLOAD_PASSWORD").expect("TRANSBEAM_UPLOAD_PASSWORD must be set!"); + let cachebuster: String = env_or_else("TRANSBEAM_CACHEBUSTER", String::new); let data = web::Data::new(AppState { file_store: RwLock::new(FileStore::load(storage_dir.clone(), max_storage_size).await?), @@ -266,9 +286,9 @@ async fn main() -> std::io::Result<()> { max_lifetime, upload_password, storage_dir, - static_dir: static_dir.clone(), reverse_proxy, mnemonic_codes, + cachebuster, }, }); start_reaper(data.clone()); @@ -281,12 +301,13 @@ async fn main() -> std::io::Result<()> { } else { Logger::default() }) + .service(index) .service(handle_download) .service(download_info) .service(handle_upload) .service(check_upload_password) .service(upload_limits) - .service(actix_files::Files::new("/", static_dir.clone()).index_file("index.html")) + .service(actix_files::Files::new("/", static_dir.clone())) }); if reverse_proxy { diff --git a/static/404.html b/static/404.html deleted file mode 100644 index bfc07c8..0000000 --- a/static/404.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - transbeam - - - -
-

The download code you entered wasn't found. The download may have expired.

-
-
- -
- -
-
-
-

< Back

-
- - - diff --git a/static/index.html b/static/index.html deleted file mode 100644 index 3719884..0000000 --- a/static/index.html +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - - - - - - transbeam - - - -
-

Download

-
-
- -
- -
-
- -
-

Uploading is currently closed.

-
-
-

Upload

-
-
-
-
- -
-
- -
-
-
-
-
-
- -
-
- -
-
-
-
-
Download code:
-
-
Link copied!
-
-
-
-
-
-
-
-
-
-
- -
- -
-
- - - diff --git a/templates/404.html b/templates/404.html new file mode 100644 index 0000000..55979fa --- /dev/null +++ b/templates/404.html @@ -0,0 +1,24 @@ +{% extends "base.html" %} + +{% block title %}Download not found - transbeam{% endblock %} + +{% block head %} + +{% endblock %} + +{% block body %} +
+

The download code you entered wasn't found. The download may have expired.

+
+
+ +
+ +
+
+
+

< Back

+
+{% endblock %} diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..0bc7050 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,27 @@ + + + + + + + + + + + {% block title %}transbeam{% endblock %} + {% block head %}{% endblock %} + + + + {% block body %}{% endblock %} + + + diff --git a/templates/download.html b/templates/download.html index a834c2a..8675972 100644 --- a/templates/download.html +++ b/templates/download.html @@ -1,52 +1,39 @@ - - - - - - - - - - - - - {{ file.name }} - transbeam - - - -
-
{{ file.name }}
-
{{ bytesize::to_string(file.size.clone(), false).replace(" ", "") }}
-
-
- {% match file.contents %} - {% when Some with (files) %} -
-
- Show file list - - {% let offsets = offsets.as_ref().unwrap() %} - {% for f in files %} - - - - - - - {% endfor %} -
{{ bytesize::to_string(f.size.clone(), false).replace(" ", "") }}{{ f.name }}
-
-
- {% else %} - {% endmatch %} - - - +{% extends "base.html" %} + +{% block title %}{{ info.file.name }} - transbeam{% endblock %} + +{% block head %} + + + +{% endblock %} + +{% block body %} +
+
{{ info.file.name }}
+
{{ bytesize::to_string(info.file.size.clone(), false).replace(" ", "") }}
+
+
+ {% match info.file.contents %} + {% when Some with (files) %} +
+
+ Show file list + + {% let offsets = info.offsets.as_ref().unwrap() %} + {% for f in files %} + + + + + + + {% endfor %} +
{{ bytesize::to_string(f.size.clone(), false).replace(" ", "") }}{{ f.name }}
+
+
+ {% else %} + {% endmatch %} +{% endblock %} diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..81b3612 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,87 @@ +{% extends "base.html" %} + +{% block head %} + + + + +{% endblock %} + +{% block body_attrs %}class="noscript landing"{% endblock %} + +{% block body %} +
+

Download

+
+
+ +
+ +
+
+ +
+

Uploading is currently closed.

+
+
+

Upload

+
+
+
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+ +
+
+
+
+
Download code:
+
+
Link copied!
+
+
+
+
+
+
+
+
+
+
+ +
+ +
+
+{% endblock %}