memorable download codes
This commit is contained in:
		
							parent
							
								
									511bd741dd
								
							
						
					
					
						commit
						86bdac20af
					
				
					 7 changed files with 31 additions and 10 deletions
				
			
		
							
								
								
									
										11
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										11
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -899,6 +899,16 @@ dependencies = [
 | 
			
		|||
 "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]]
 | 
			
		||||
name = "ntapi"
 | 
			
		||||
version = "0.3.7"
 | 
			
		||||
| 
						 | 
				
			
			@ -1408,6 +1418,7 @@ dependencies = [
 | 
			
		|||
 "inotify",
 | 
			
		||||
 "log",
 | 
			
		||||
 "mime",
 | 
			
		||||
 "mnemonic",
 | 
			
		||||
 "pin-project-lite",
 | 
			
		||||
 "rand",
 | 
			
		||||
 "sanitise-file-name",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,7 @@ futures-core = "0.3"
 | 
			
		|||
inotify = "0.10"
 | 
			
		||||
log = "0.4"
 | 
			
		||||
mime = "0.3.16"
 | 
			
		||||
mnemonic = "1.0.1"
 | 
			
		||||
pin-project-lite = "0.2.9"
 | 
			
		||||
rand = "0.8.5"
 | 
			
		||||
sanitise-file-name = "1.0.0"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,6 +8,7 @@
 | 
			
		|||
 | 
			
		||||
- One-to-many transfer of large files
 | 
			
		||||
- 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
 | 
			
		||||
  wait for the upload to finish
 | 
			
		||||
- 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)
 | 
			
		||||
- `TRANSBEAM_MAX_STORAGE_SIZE`: maximum total size, in bytes, of all
 | 
			
		||||
  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
 | 
			
		||||
  submodules/libraries. See
 | 
			
		||||
  [`env_logger`](https://docs.rs/env_logger/latest/env_logger/)'s
 | 
			
		||||
| 
						 | 
				
			
			@ -58,5 +62,3 @@ cargo run --release
 | 
			
		|||
 | 
			
		||||
- uploader auth
 | 
			
		||||
- downloader auth
 | 
			
		||||
- more readable download codes?
 | 
			
		||||
- proper error display in the web ui
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,6 @@
 | 
			
		|||
mod download;
 | 
			
		||||
mod store;
 | 
			
		||||
mod upload;
 | 
			
		||||
mod util;
 | 
			
		||||
mod zip;
 | 
			
		||||
 | 
			
		||||
use std::{fs::File, path::PathBuf};
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +24,7 @@ async fn handle_download(
 | 
			
		|||
    data: AppData,
 | 
			
		||||
) -> actix_web::Result<HttpResponse> {
 | 
			
		||||
    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());
 | 
			
		||||
    }
 | 
			
		||||
    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 log::{debug, error, info, warn};
 | 
			
		||||
use rand::{distributions::{Alphanumeric, DistString}, thread_rng, Rng};
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
use time::OffsetDateTime;
 | 
			
		||||
use tokio::{
 | 
			
		||||
| 
						 | 
				
			
			@ -15,6 +16,17 @@ const GIGA: u64 = 1024*1024*1024;
 | 
			
		|||
const DEFAULT_MAX_UPLOAD_SIZE: u64 = 16*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 {
 | 
			
		||||
    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
 | 
			
		||||
                    // want to try to delete it if it's not the sort
 | 
			
		||||
                    // 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);
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,7 +5,6 @@ use actix_http::ws::{CloseReason, Item};
 | 
			
		|||
use actix_web_actors::ws::{self, CloseCode};
 | 
			
		||||
use bytes::Bytes;
 | 
			
		||||
use log::{debug, error, info, trace};
 | 
			
		||||
use rand::distributions::{Alphanumeric, DistString};
 | 
			
		||||
use serde::{Deserialize, Serialize};
 | 
			
		||||
use time::OffsetDateTime;
 | 
			
		||||
use unicode_normalization::UnicodeNormalization;
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +67,7 @@ impl Uploader {
 | 
			
		|||
    pub(crate) fn new(app_data: super::AppData) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            writer: None,
 | 
			
		||||
            storage_filename: Alphanumeric.sample_string(&mut rand::thread_rng(), 8),
 | 
			
		||||
            storage_filename: store::gen_storage_code(),
 | 
			
		||||
            app_data,
 | 
			
		||||
            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…
	
	Add table
		Add a link
		
	
		Reference in a new issue