add 404 page for incorrect download codes

This commit is contained in:
xenofem 2022-05-03 18:31:50 -04:00
parent 106c99d398
commit 9d87934cf4
8 changed files with 92 additions and 36 deletions

View file

@ -5,8 +5,10 @@ mod zip;
use std::{fmt::Debug, fs::File, path::PathBuf, str::FromStr}; use std::{fmt::Debug, fs::File, path::PathBuf, str::FromStr};
use actix_files::NamedFile;
use actix_web::{ use actix_web::{
get, middleware::Logger, post, web, App, HttpRequest, HttpResponse, HttpServer, Responder, get, http::StatusCode, middleware::Logger, post, web, App, HttpRequest, HttpResponse,
HttpServer, Responder,
}; };
use actix_web_actors::ws; use actix_web_actors::ws;
use bytesize::ByteSize; use bytesize::ByteSize;
@ -27,6 +29,7 @@ struct Config {
max_lifetime: u16, max_lifetime: u16,
upload_password: String, upload_password: String,
storage_dir: PathBuf, storage_dir: PathBuf,
static_dir: PathBuf,
reverse_proxy: bool, reverse_proxy: bool,
mnemonic_codes: bool, mnemonic_codes: bool,
} }
@ -57,14 +60,11 @@ async fn handle_download(
download: web::Query<DownloadRequest>, download: web::Query<DownloadRequest>,
data: web::Data<AppState>, data: web::Data<AppState>,
) -> actix_web::Result<HttpResponse> { ) -> actix_web::Result<HttpResponse> {
let ip_addr = get_ip_addr(&req, data.config.reverse_proxy);
let code = &download.code; let code = &download.code;
if !store::is_valid_storage_code(code) { if !store::is_valid_storage_code(code) {
log_auth_failure(&ip_addr); return download_not_found(req, data);
return Ok(HttpResponse::NotFound().finish());
} }
let file_store = data.file_store.read().await; let info = data.file_store.read().await.lookup_file(code);
let info = file_store.lookup_file(code);
if let Some(info) = info { if let Some(info) = info {
let storage_path = data.config.storage_dir.join(code); let storage_path = data.config.storage_dir.join(code);
let file = File::open(&storage_path)?; let file = File::open(&storage_path)?;
@ -75,11 +75,21 @@ async fn handle_download(
} }
.into_response(&req)) .into_response(&req))
} else { } else {
log_auth_failure(&ip_addr); download_not_found(req, data)
Ok(HttpResponse::NotFound().finish())
} }
} }
fn download_not_found(
req: HttpRequest,
data: web::Data<AppState>,
) -> actix_web::Result<HttpResponse> {
let ip_addr = get_ip_addr(&req, data.config.reverse_proxy);
log_auth_failure(&ip_addr);
Ok(NamedFile::open(data.config.static_dir.join("404.html"))?
.set_status_code(StatusCode::NOT_FOUND)
.into_response(&req))
}
#[get("/upload")] #[get("/upload")]
async fn handle_upload( async fn handle_upload(
req: HttpRequest, req: HttpRequest,
@ -183,6 +193,7 @@ async fn main() -> std::io::Result<()> {
max_lifetime, max_lifetime,
upload_password, upload_password,
storage_dir, storage_dir,
static_dir: static_dir.clone(),
reverse_proxy, reverse_proxy,
mnemonic_codes, mnemonic_codes,
}, },

38
static/404.html Normal file
View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" type="text/css" href="css/transbeam.css"/>
<link rel="apple-touch-icon" href="images/site-icons/transbeam-apple.png"/>
<link rel="manifest" href="manifest.json"/>
<script src="js/download.js"></script>
<title>transbeam</title>
</head>
<body>
<div id="header">
<a href="./">
<img src="images/site-icons/transbeam.svg" height="128">
<h1>transbeam</h1>
</a>
</div>
<div id="download" class="section">
<h3>The download code you entered wasn't found. The download may have expired.</h3>
<form id="download_form" action="download" method="get">
<div>
<label>
<input type="text" id="download_code_input" name="code" placeholder="Download code"/>
</label>
</div>
<input id="download_button" type="submit" value="Download"/>
</form>
</div>
<div class="section">
<a href="./"><h3>&lt; Back</h3></a>
</div>
<div id="footer">
<h5>(c) 2022 xenofem, MIT licensed</h5>
<h5><a target="_blank" href="https://git.xeno.science/xenofem/transbeam">source</a></h5>
</div>
</body>
</html>

View file

@ -8,6 +8,11 @@ body {
#header h1 { #header h1 {
margin-top: 5px; margin-top: 5px;
color: black;
}
#header a {
text-decoration: none;
} }
#message { #message {

View file

@ -3,12 +3,13 @@
<head> <head>
<meta charset="utf-8"/> <meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/> <meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" type="text/css" href="transbeam.css"/> <link rel="stylesheet" type="text/css" href="css/transbeam.css"/>
<link rel="stylesheet" type="text/css" href="states.css"/> <link rel="stylesheet" type="text/css" href="css/states.css"/>
<link rel="apple-touch-icon" href="images/site-icons/transbeam-apple.png"/> <link rel="apple-touch-icon" href="images/site-icons/transbeam-apple.png"/>
<link rel="manifest" href="manifest.json"/> <link rel="manifest" href="manifest.json"/>
<script src="util.js"></script> <script src="js/util.js"></script>
<script src="transbeam.js"></script> <script src="js/download.js"></script>
<script src="js/upload.js"></script>
<title>transbeam</title> <title>transbeam</title>
</head> </head>
<body class="noscript landing"> <body class="noscript landing">

25
static/js/download.js Normal file
View file

@ -0,0 +1,25 @@
document.addEventListener('DOMContentLoaded', () => {
const downloadCodeInput = document.getElementById('download_code_input');
const downloadButton = document.getElementById('download_button');
const downloadForm = document.getElementById('download_form');
downloadCodeInput.addEventListener('beforeinput', (e) => {
if (/^[a-zA-Z0-9-]+$/.test(e.data)) { return; }
e.preventDefault();
if (e.data === ' ') {
downloadCodeInput.value += '-';
}
});
const disableEnableDownload = () => { downloadButton.disabled = (downloadCodeInput.value === ''); };
disableEnableDownload();
downloadCodeInput.addEventListener('input', disableEnableDownload);
downloadForm.addEventListener('submit', (e) => {
if (downloadCodeInput.value === '') {
e.preventDefault();
} else {
setTimeout(() => {
downloadCodeInput.value = '';
downloadButton.disabled = true;
}, 0);
}
});
});

View file

@ -71,30 +71,6 @@ document.addEventListener('DOMContentLoaded', () => {
downloadCodeContainer.addEventListener('mouseleave', () => { downloadCodeContainer.addEventListener('mouseleave', () => {
downloadCodeContainer.className = ''; downloadCodeContainer.className = '';
}); });
const downloadCodeInput = document.getElementById('download_code_input');
const downloadButton = document.getElementById('download_button');
const downloadForm = document.getElementById('download_form');
downloadCodeInput.addEventListener('beforeinput', (e) => {
if (/^[a-zA-Z0-9-]+$/.test(e.data)) { return; }
e.preventDefault();
if (e.data === ' ') {
downloadCodeInput.value += '-';
}
});
const disableEnableDownload = () => { downloadButton.disabled = (downloadCodeInput.value === ''); };
disableEnableDownload();
downloadCodeInput.addEventListener('input', disableEnableDownload);
downloadForm.addEventListener('submit', (e) => {
if (downloadCodeInput.value === '') {
e.preventDefault();
} else {
setTimeout(() => {
downloadCodeInput.value = '';
downloadButton.disabled = true;
}, 0);
}
});
}); });
function updateFiles() { function updateFiles() {