Handle file uploads with a validated session
This commit is contained in:
parent
9bb32a378c
commit
c38d680e57
|
@ -7,3 +7,4 @@ result
|
|||
file-service/*.sqlite
|
||||
file-service/*.sqlite-shm
|
||||
file-service/*.sqlite-wal
|
||||
file-service/var
|
||||
|
|
|
@ -1,7 +1,12 @@
|
|||
use build_html::Html;
|
||||
use bytes::Buf;
|
||||
use cookie::time::error::Format;
|
||||
use file_service::WriteFileError;
|
||||
use futures_util::StreamExt;
|
||||
use http::{Error, StatusCode};
|
||||
use std::collections::HashMap;
|
||||
use warp::http::Response;
|
||||
use std::io::Read;
|
||||
use warp::{filters::multipart::FormData, http::Response, multipart::Part};
|
||||
|
||||
use crate::{pages, App, AuthToken, FileId, FileInfo, ReadFileError, SessionToken};
|
||||
|
||||
|
@ -97,11 +102,27 @@ pub async fn handle_auth(
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn handle_upload(app: App, token: SessionToken) -> Result<http::Response<String>, Error> {
|
||||
pub async fn handle_upload(
|
||||
app: App,
|
||||
token: SessionToken,
|
||||
form: FormData,
|
||||
) -> Result<http::Response<String>, Error> {
|
||||
match app.validate_session(token).await {
|
||||
Ok(Some(_)) => Response::builder()
|
||||
.status(StatusCode::NOT_IMPLEMENTED)
|
||||
.body("".to_owned()),
|
||||
Ok(Some(_)) => match process_file_upload(app, form).await {
|
||||
Ok(_) => Response::builder()
|
||||
.header("location", "/")
|
||||
.status(StatusCode::SEE_OTHER)
|
||||
.body("".to_owned()),
|
||||
Err(UploadError::FilenameMissing) => Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body("filename is required for all files".to_owned()),
|
||||
Err(UploadError::WriteFileError(err)) => Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(format!("could not write to the file system: {:?}", err)),
|
||||
Err(UploadError::WarpError(err)) => Response::builder()
|
||||
.status(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
.body(format!("error with the app framework: {:?}", err)),
|
||||
},
|
||||
_ => Response::builder()
|
||||
.status(StatusCode::UNAUTHORIZED)
|
||||
.body("".to_owned()),
|
||||
|
@ -133,3 +154,102 @@ where
|
|||
},
|
||||
}
|
||||
}
|
||||
|
||||
async fn collect_multipart(
|
||||
mut stream: warp::filters::multipart::FormData,
|
||||
) -> Result<Vec<(Option<String>, Option<String>, Vec<u8>)>, warp::Error> {
|
||||
let mut content: Vec<(Option<String>, Option<String>, Vec<u8>)> = Vec::new();
|
||||
|
||||
while let Some(part) = stream.next().await {
|
||||
match part {
|
||||
Ok(part) => content.push(collect_content(part).await.unwrap()),
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(content)
|
||||
}
|
||||
|
||||
async fn collect_content(
|
||||
mut part: Part,
|
||||
) -> Result<(Option<String>, Option<String>, Vec<u8>), String> {
|
||||
let mut content: Vec<u8> = Vec::new();
|
||||
|
||||
while let Some(Ok(data)) = part.data().await {
|
||||
let mut reader = data.reader();
|
||||
reader.read_to_end(&mut content).unwrap();
|
||||
}
|
||||
|
||||
Ok((
|
||||
part.content_type().map(|s| s.to_owned()),
|
||||
part.filename().map(|s| s.to_owned()),
|
||||
content,
|
||||
))
|
||||
}
|
||||
|
||||
/*
|
||||
async fn handle_upload(
|
||||
form: warp::filters::multipart::FormData,
|
||||
app: App,
|
||||
) -> warp::http::Result<warp::http::Response<String>> {
|
||||
let files = collect_multipart(form).await;
|
||||
match files {
|
||||
Ok(files) => {
|
||||
for (_, filename, content) in files {
|
||||
match filename {
|
||||
Some(filename) => {
|
||||
app.add_file(filename, content).unwrap();
|
||||
}
|
||||
None => {
|
||||
return warp::http::Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body("".to_owned())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_err) => {
|
||||
return warp::http::Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body("".to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
// println!("file length: {:?}", files.map(|f| f.len()));
|
||||
warp::http::Response::builder()
|
||||
.header("location", "/")
|
||||
.status(StatusCode::SEE_OTHER)
|
||||
.body("".to_owned())
|
||||
}
|
||||
*/
|
||||
|
||||
enum UploadError {
|
||||
FilenameMissing,
|
||||
WriteFileError(WriteFileError),
|
||||
WarpError(warp::Error),
|
||||
}
|
||||
|
||||
impl From<WriteFileError> for UploadError {
|
||||
fn from(err: WriteFileError) -> Self {
|
||||
Self::WriteFileError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<warp::Error> for UploadError {
|
||||
fn from(err: warp::Error) -> Self {
|
||||
Self::WarpError(err)
|
||||
}
|
||||
}
|
||||
|
||||
async fn process_file_upload(app: App, form: FormData) -> Result<(), UploadError> {
|
||||
let files = collect_multipart(form).await?;
|
||||
for (_, filename, content) in files {
|
||||
match filename {
|
||||
Some(filename) => {
|
||||
app.add_file(filename, content).await?;
|
||||
}
|
||||
None => return Err(UploadError::FilenameMissing),
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -42,75 +42,12 @@ async fn authenticate_user(app: App, auth_token: String) -> Result<Username, war
|
|||
*/
|
||||
|
||||
/*
|
||||
async fn collect_content(
|
||||
mut part: Part,
|
||||
) -> Result<(Option<String>, Option<String>, Vec<u8>), String> {
|
||||
let mut content: Vec<u8> = Vec::new();
|
||||
|
||||
while let Some(Ok(data)) = part.data().await {
|
||||
let mut reader = data.reader();
|
||||
reader.read_to_end(&mut content).unwrap();
|
||||
}
|
||||
|
||||
Ok((
|
||||
part.content_type().map(|s| s.to_owned()),
|
||||
part.filename().map(|s| s.to_owned()),
|
||||
content,
|
||||
))
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
async fn collect_multipart(
|
||||
mut stream: warp::filters::multipart::FormData,
|
||||
) -> Result<Vec<(Option<String>, Option<String>, Vec<u8>)>, warp::Error> {
|
||||
let mut content: Vec<(Option<String>, Option<String>, Vec<u8>)> = Vec::new();
|
||||
|
||||
while let Some(part) = stream.next().await {
|
||||
match part {
|
||||
Ok(part) => content.push(collect_content(part).await.unwrap()),
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(content)
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
async fn handle_upload(
|
||||
form: warp::filters::multipart::FormData,
|
||||
app: App,
|
||||
) -> warp::http::Result<warp::http::Response<String>> {
|
||||
let files = collect_multipart(form).await;
|
||||
match files {
|
||||
Ok(files) => {
|
||||
for (_, filename, content) in files {
|
||||
match filename {
|
||||
Some(filename) => {
|
||||
app.add_file(filename, content).unwrap();
|
||||
}
|
||||
None => {
|
||||
return warp::http::Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body("".to_owned())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_err) => {
|
||||
return warp::http::Response::builder()
|
||||
.status(StatusCode::BAD_REQUEST)
|
||||
.body("".to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
// println!("file length: {:?}", files.map(|f| f.len()));
|
||||
warp::http::Response::builder()
|
||||
.header("location", "/")
|
||||
.status(StatusCode::SEE_OTHER)
|
||||
.body("".to_owned())
|
||||
}
|
||||
*/
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -204,13 +141,6 @@ pub async fn main() {
|
|||
|
||||
let app = App::new(authdb, store);
|
||||
|
||||
/*
|
||||
let with_app = {
|
||||
let app = app.clone();
|
||||
warp::any().map(move || app.clone())
|
||||
};
|
||||
*/
|
||||
|
||||
let log = warp::log("file_service");
|
||||
let root = warp::path!()
|
||||
.and(warp::get())
|
||||
|
@ -228,6 +158,7 @@ pub async fn main() {
|
|||
.and(warp::post())
|
||||
.and(with_app(app.clone()))
|
||||
.and(with_session())
|
||||
.and(warp::multipart::form())
|
||||
.then(handle_upload);
|
||||
|
||||
let thumbnail = warp::path!(String / "tn")
|
||||
|
@ -243,13 +174,11 @@ pub async fn main() {
|
|||
.then(move |id, old_etags, app: App| file(app, id, old_etags));
|
||||
|
||||
let server = warp::serve(
|
||||
root.or(auth).or(upload_via_form).with(log), /*
|
||||
root.or(auth)
|
||||
.or(thumbnail)
|
||||
.or(file)
|
||||
.or(upload_handler)
|
||||
.with(log),
|
||||
*/
|
||||
root.or(auth)
|
||||
.or(upload_via_form)
|
||||
.or(thumbnail)
|
||||
.or(file)
|
||||
.with(log),
|
||||
);
|
||||
|
||||
server
|
||||
|
|
Loading…
Reference in New Issue