Whitelist / better duplicate file response
This commit is contained in:
parent
1a27f19e50
commit
f16e7acadb
@ -11,4 +11,7 @@ storage_dir = "./data"
|
|||||||
max_upload_bytes = 104857600
|
max_upload_bytes = 104857600
|
||||||
|
|
||||||
# Public facing url
|
# Public facing url
|
||||||
public_url = "http://localhost:8000"
|
public_url = "http://localhost:8000"
|
||||||
|
|
||||||
|
# Whitelisted pubkeys, leave out to disable
|
||||||
|
# whitelist = ["63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed"]
|
@ -26,14 +26,14 @@ pub struct FileSystemResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct FileStore {
|
pub struct FileStore {
|
||||||
path: String,
|
settings: Settings,
|
||||||
processor: Arc<Mutex<MediaProcessor>>,
|
processor: Arc<Mutex<MediaProcessor>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FileStore {
|
impl FileStore {
|
||||||
pub fn new(settings: Settings) -> Self {
|
pub fn new(settings: Settings) -> Self {
|
||||||
Self {
|
Self {
|
||||||
path: settings.storage_dir,
|
settings,
|
||||||
processor: Arc::new(Mutex::new(MediaProcessor::new())),
|
processor: Arc::new(Mutex::new(MediaProcessor::new())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,6 +50,10 @@ impl FileStore {
|
|||||||
{
|
{
|
||||||
let result = self.store_compress_file(stream, mime_type, compress).await?;
|
let result = self.store_compress_file(stream, mime_type, compress).await?;
|
||||||
let dst_path = self.map_path(&result.sha256);
|
let dst_path = self.map_path(&result.sha256);
|
||||||
|
if dst_path.exists() {
|
||||||
|
fs::remove_file(&result.path)?;
|
||||||
|
return Err(Error::msg("File already exists"));
|
||||||
|
}
|
||||||
fs::create_dir_all(dst_path.parent().unwrap())?;
|
fs::create_dir_all(dst_path.parent().unwrap())?;
|
||||||
if let Err(e) = fs::copy(&result.path, &dst_path) {
|
if let Err(e) = fs::copy(&result.path, &dst_path) {
|
||||||
fs::remove_file(&result.path)?;
|
fs::remove_file(&result.path)?;
|
||||||
@ -71,6 +75,7 @@ impl FileStore {
|
|||||||
let tmp_path = FileStore::map_temp(random_id);
|
let tmp_path = FileStore::map_temp(random_id);
|
||||||
let mut file = File::options()
|
let mut file = File::options()
|
||||||
.create(true)
|
.create(true)
|
||||||
|
.truncate(false)
|
||||||
.write(true)
|
.write(true)
|
||||||
.read(true)
|
.read(true)
|
||||||
.open(tmp_path.clone())
|
.open(tmp_path.clone())
|
||||||
@ -83,7 +88,7 @@ impl FileStore {
|
|||||||
let start = SystemTime::now();
|
let start = SystemTime::now();
|
||||||
let proc_result = {
|
let proc_result = {
|
||||||
let mut p_lock = self.processor.lock().expect("asd");
|
let mut p_lock = self.processor.lock().expect("asd");
|
||||||
p_lock.process_file(tmp_path.clone(), &mime_type)?
|
p_lock.process_file(tmp_path.clone(), mime_type)?
|
||||||
};
|
};
|
||||||
if let FileProcessorResult::NewFile(new_temp) = proc_result {
|
if let FileProcessorResult::NewFile(new_temp) = proc_result {
|
||||||
let old_size = tmp_path.metadata()?.len();
|
let old_size = tmp_path.metadata()?.len();
|
||||||
@ -99,6 +104,7 @@ impl FileStore {
|
|||||||
fs::remove_file(tmp_path)?;
|
fs::remove_file(tmp_path)?;
|
||||||
file = File::options()
|
file = File::options()
|
||||||
.create(true)
|
.create(true)
|
||||||
|
.truncate(false)
|
||||||
.write(true)
|
.write(true)
|
||||||
.read(true)
|
.read(true)
|
||||||
.open(new_temp.result.clone())
|
.open(new_temp.result.clone())
|
||||||
@ -150,9 +156,9 @@ impl FileStore {
|
|||||||
|
|
||||||
fn map_path(&self, id: &Vec<u8>) -> PathBuf {
|
fn map_path(&self, id: &Vec<u8>) -> PathBuf {
|
||||||
let id = hex::encode(id);
|
let id = hex::encode(id);
|
||||||
Path::new(&self.path)
|
Path::new(&self.settings.storage_dir)
|
||||||
.join(id[0..2].to_string())
|
.join(&id[0..2])
|
||||||
.join(id[2..4].to_string())
|
.join(&id[2..4])
|
||||||
.join(id)
|
.join(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
use std::fs;
|
||||||
|
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
use log::error;
|
use log::error;
|
||||||
use nostr::prelude::hex;
|
use nostr::prelude::hex;
|
||||||
@ -105,6 +107,12 @@ async fn upload(
|
|||||||
.content_type
|
.content_type
|
||||||
.unwrap_or("application/octet-stream".to_string());
|
.unwrap_or("application/octet-stream".to_string());
|
||||||
|
|
||||||
|
// check whitelist
|
||||||
|
if let Some(wl) = &settings.whitelist {
|
||||||
|
if !wl.contains(&auth.event.pubkey.to_hex()) {
|
||||||
|
return BlossomResponse::error("Not on whitelist");
|
||||||
|
}
|
||||||
|
}
|
||||||
match fs
|
match fs
|
||||||
.put(data.open(ByteUnit::from(settings.max_upload_bytes)), &mime_type, false)
|
.put(data.open(ByteUnit::from(settings.max_upload_bytes)), &mime_type, false)
|
||||||
.await
|
.await
|
||||||
@ -126,7 +134,15 @@ async fn upload(
|
|||||||
created: Utc::now(),
|
created: Utc::now(),
|
||||||
};
|
};
|
||||||
if let Err(e) = db.add_file(&f).await {
|
if let Err(e) = db.add_file(&f).await {
|
||||||
error!("{:?}", e);
|
error!("{}", e.to_string());
|
||||||
|
let _ = fs::remove_file(blob.path);
|
||||||
|
if let Some(dbe) = e.as_database_error() {
|
||||||
|
if let Some(c) = dbe.code() {
|
||||||
|
if c == "23000" {
|
||||||
|
return BlossomResponse::error("File already exists");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BlossomResponse::error(format!("Error saving file (db): {}", e))
|
BlossomResponse::error(format!("Error saving file (db): {}", e))
|
||||||
} else {
|
} else {
|
||||||
BlossomResponse::BlobDescriptor(Json(BlobDescriptor::from_upload(
|
BlossomResponse::BlobDescriptor(Json(BlobDescriptor::from_upload(
|
||||||
@ -136,7 +152,7 @@ async fn upload(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("{:?}", e);
|
error!("{}", e.to_string());
|
||||||
BlossomResponse::error(format!("Error saving file (disk): {}", e))
|
BlossomResponse::error(format!("Error saving file (disk): {}", e))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
|
use std::borrow::Cow;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::fs;
|
||||||
|
|
||||||
use chrono::Utc;
|
use chrono::Utc;
|
||||||
|
use libc::remove;
|
||||||
|
use log::error;
|
||||||
use rocket::{FromForm, Responder, Route, routes, State};
|
use rocket::{FromForm, Responder, Route, routes, State};
|
||||||
use rocket::form::Form;
|
use rocket::form::Form;
|
||||||
use rocket::fs::TempFile;
|
use rocket::fs::TempFile;
|
||||||
@ -158,6 +162,13 @@ async fn upload(
|
|||||||
};
|
};
|
||||||
let mime_type = form.media_type
|
let mime_type = form.media_type
|
||||||
.unwrap_or("application/octet-stream");
|
.unwrap_or("application/octet-stream");
|
||||||
|
|
||||||
|
// check whitelist
|
||||||
|
if let Some(wl) = &settings.whitelist {
|
||||||
|
if !wl.contains(&auth.event.pubkey.to_hex()) {
|
||||||
|
return Nip96Response::error("Not on whitelist");
|
||||||
|
}
|
||||||
|
}
|
||||||
match fs
|
match fs
|
||||||
.put(file, mime_type, true)
|
.put(file, mime_type, true)
|
||||||
.await
|
.await
|
||||||
@ -180,6 +191,15 @@ async fn upload(
|
|||||||
created: Utc::now(),
|
created: Utc::now(),
|
||||||
};
|
};
|
||||||
if let Err(e) = db.add_file(&file_upload).await {
|
if let Err(e) = db.add_file(&file_upload).await {
|
||||||
|
error!("{}", e.to_string());
|
||||||
|
let _ = fs::remove_file(blob.path);
|
||||||
|
if let Some(dbe) = e.as_database_error() {
|
||||||
|
if let Some(c) = dbe.code() {
|
||||||
|
if c == "23000" {
|
||||||
|
return Nip96Response::error("File already exists");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return Nip96Response::error(&format!("Could not save file (db): {}", e));
|
return Nip96Response::error(&format!("Could not save file (db): {}", e));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,7 +227,10 @@ async fn upload(
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Err(e) => return Nip96Response::error(&format!("Could not save file: {}", e)),
|
Err(e) => {
|
||||||
|
error!("{}", e.to_string());
|
||||||
|
Nip96Response::error(&format!("Could not save file: {}", e))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,4 +16,7 @@ pub struct Settings {
|
|||||||
|
|
||||||
/// Public facing url
|
/// Public facing url
|
||||||
pub public_url: String,
|
pub public_url: String,
|
||||||
|
|
||||||
|
/// Whitelisted pubkeys
|
||||||
|
pub whitelist: Option<Vec<String>>
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user