memorable download codes
This commit is contained in:
parent
511bd741dd
commit
86bdac20af
11
Cargo.lock
generated
11
Cargo.lock
generated
|
@ -899,6 +899,16 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mnemonic"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29fae0e4c0b155d3b019a7cbc27abe4a90e15c06814d27889ce9f5f44e2faf77"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ntapi"
|
name = "ntapi"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
|
@ -1408,6 +1418,7 @@ dependencies = [
|
||||||
"inotify",
|
"inotify",
|
||||||
"log",
|
"log",
|
||||||
"mime",
|
"mime",
|
||||||
|
"mnemonic",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"rand",
|
"rand",
|
||||||
"sanitise-file-name",
|
"sanitise-file-name",
|
||||||
|
|
|
@ -20,6 +20,7 @@ futures-core = "0.3"
|
||||||
inotify = "0.10"
|
inotify = "0.10"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
mime = "0.3.16"
|
mime = "0.3.16"
|
||||||
|
mnemonic = "1.0.1"
|
||||||
pin-project-lite = "0.2.9"
|
pin-project-lite = "0.2.9"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
sanitise-file-name = "1.0.0"
|
sanitise-file-name = "1.0.0"
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
- One-to-many transfer of large files
|
- One-to-many transfer of large files
|
||||||
- Simple web UI for sender and receivers
|
- Simple web UI for sender and receivers
|
||||||
|
- Word-based download codes that are easy to remember and communicate
|
||||||
- Receivers can begin downloading *immediately*, without needing to
|
- Receivers can begin downloading *immediately*, without needing to
|
||||||
wait for the upload to finish
|
wait for the upload to finish
|
||||||
- Receivers can also download after the upload is complete and the
|
- Receivers can also download after the upload is complete and the
|
||||||
|
@ -29,6 +30,9 @@ transbeam is configured with the following environment variables:
|
||||||
being uploaded (default: 16GiB)
|
being uploaded (default: 16GiB)
|
||||||
- `TRANSBEAM_MAX_STORAGE_SIZE`: maximum total size, in bytes, of all
|
- `TRANSBEAM_MAX_STORAGE_SIZE`: maximum total size, in bytes, of all
|
||||||
files being stored by transbeam (default: 64GiB)
|
files being stored by transbeam (default: 64GiB)
|
||||||
|
- `TRANSBEAM_MNEMONIC_CODES`: generate memorable download codes using
|
||||||
|
English words, rather than random alphanumeric strings (default:
|
||||||
|
true)
|
||||||
- `RUST_LOG`: log levels, for the app as a whole and/or for specific
|
- `RUST_LOG`: log levels, for the app as a whole and/or for specific
|
||||||
submodules/libraries. See
|
submodules/libraries. See
|
||||||
[`env_logger`](https://docs.rs/env_logger/latest/env_logger/)'s
|
[`env_logger`](https://docs.rs/env_logger/latest/env_logger/)'s
|
||||||
|
@ -58,5 +62,3 @@ cargo run --release
|
||||||
|
|
||||||
- uploader auth
|
- uploader auth
|
||||||
- downloader auth
|
- downloader auth
|
||||||
- more readable download codes?
|
|
||||||
- proper error display in the web ui
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
mod download;
|
mod download;
|
||||||
mod store;
|
mod store;
|
||||||
mod upload;
|
mod upload;
|
||||||
mod util;
|
|
||||||
mod zip;
|
mod zip;
|
||||||
|
|
||||||
use std::{fs::File, path::PathBuf};
|
use std::{fs::File, path::PathBuf};
|
||||||
|
@ -25,7 +24,7 @@ async fn handle_download(
|
||||||
data: AppData,
|
data: AppData,
|
||||||
) -> actix_web::Result<HttpResponse> {
|
) -> actix_web::Result<HttpResponse> {
|
||||||
let file_code = path.into_inner();
|
let file_code = path.into_inner();
|
||||||
if !util::is_ascii_alphanumeric(&file_code) {
|
if !store::is_valid_storage_code(&file_code) {
|
||||||
return Ok(HttpResponse::NotFound().finish());
|
return Ok(HttpResponse::NotFound().finish());
|
||||||
}
|
}
|
||||||
let data = data.read().await;
|
let data = data.read().await;
|
||||||
|
|
14
src/store.rs
14
src/store.rs
|
@ -1,6 +1,7 @@
|
||||||
use std::{collections::HashMap, io::ErrorKind, path::PathBuf, str::FromStr};
|
use std::{collections::HashMap, io::ErrorKind, path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
use log::{debug, error, info, warn};
|
use log::{debug, error, info, warn};
|
||||||
|
use rand::{distributions::{Alphanumeric, DistString}, thread_rng, Rng};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use tokio::{
|
use tokio::{
|
||||||
|
@ -15,6 +16,17 @@ const GIGA: u64 = 1024*1024*1024;
|
||||||
const DEFAULT_MAX_UPLOAD_SIZE: u64 = 16*GIGA;
|
const DEFAULT_MAX_UPLOAD_SIZE: u64 = 16*GIGA;
|
||||||
const DEFAULT_MAX_STORAGE_SIZE: u64 = 64*GIGA;
|
const DEFAULT_MAX_STORAGE_SIZE: u64 = 64*GIGA;
|
||||||
|
|
||||||
|
pub fn gen_storage_code() -> String {
|
||||||
|
if std::env::var("TRANSBEAM_MNEMONIC_CODES").as_deref() == Ok("false") {
|
||||||
|
Alphanumeric.sample_string(&mut thread_rng(), 8)
|
||||||
|
} else {
|
||||||
|
mnemonic::to_string(thread_rng().gen::<[u8; 4]>())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_valid_storage_code(s: &str) -> bool {
|
||||||
|
s.as_bytes().iter().all(|c| c.is_ascii_alphanumeric() || c == &b'-')
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn storage_dir() -> PathBuf {
|
pub(crate) fn storage_dir() -> PathBuf {
|
||||||
PathBuf::from(std::env::var("TRANSBEAM_STORAGE_DIR").unwrap_or_else(|_| String::from(DEFAULT_STORAGE_DIR)))
|
PathBuf::from(std::env::var("TRANSBEAM_STORAGE_DIR").unwrap_or_else(|_| String::from(DEFAULT_STORAGE_DIR)))
|
||||||
|
@ -133,7 +145,7 @@ impl FileStore {
|
||||||
// Handle this case separately, because we don't
|
// Handle this case separately, because we don't
|
||||||
// want to try to delete it if it's not the sort
|
// want to try to delete it if it's not the sort
|
||||||
// of path we're expecting
|
// of path we're expecting
|
||||||
if !crate::util::is_ascii_alphanumeric(&key) {
|
if !is_valid_storage_code(&key) {
|
||||||
error!("Invalid key in persistent storage: {}", key);
|
error!("Invalid key in persistent storage: {}", key);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ use actix_http::ws::{CloseReason, Item};
|
||||||
use actix_web_actors::ws::{self, CloseCode};
|
use actix_web_actors::ws::{self, CloseCode};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use log::{debug, error, info, trace};
|
use log::{debug, error, info, trace};
|
||||||
use rand::distributions::{Alphanumeric, DistString};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
use unicode_normalization::UnicodeNormalization;
|
use unicode_normalization::UnicodeNormalization;
|
||||||
|
@ -68,7 +67,7 @@ impl Uploader {
|
||||||
pub(crate) fn new(app_data: super::AppData) -> Self {
|
pub(crate) fn new(app_data: super::AppData) -> Self {
|
||||||
Self {
|
Self {
|
||||||
writer: None,
|
writer: None,
|
||||||
storage_filename: Alphanumeric.sample_string(&mut rand::thread_rng(), 8),
|
storage_filename: store::gen_storage_code(),
|
||||||
app_data,
|
app_data,
|
||||||
bytes_remaining: 0,
|
bytes_remaining: 0,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
pub(crate) fn is_ascii_alphanumeric(s: &str) -> bool {
|
|
||||||
s.as_bytes().iter().all(|c| c.is_ascii_alphanumeric())
|
|
||||||
}
|
|
Loading…
Reference in a new issue