/* use iron::headers; use iron::middleware::Handler; use iron::modifiers::{Header, Redirect}; use iron::prelude::*; use iron::response::BodyReader; use iron::status; */ use http::status::StatusCode; // use mustache::{compile_path, Template}; // use orizentic::{Permissions, ResourceName, Secret}; use build_html::Html; use std::{ io::Read, net::{IpAddr, Ipv4Addr, SocketAddr}, path::Path, sync::{Arc, RwLock}, }; use warp::Filter; mod cookies; mod html; mod lib; mod middleware; mod pages; use lib::{utils::append_extension, App, File, FileError, FileInfo}; /* fn is_admin(resource: &ResourceName, permissions: &Permissions) -> bool { let Permissions(perms) = permissions; ResourceName(String::from( "https://savanni.luminescent-dreams.com/file-service/", )) == *resource && perms.contains(&String::from("admin")) } pub fn compare_etags(info: FileInfo, etag_list: &headers::IfNoneMatch) -> bool { let current_etag = headers::EntityTag::new(false, info.hash); match etag_list { headers::IfNoneMatch::Any => false, headers::IfNoneMatch::Items(lst) => lst.iter().any(|etag| etag.weak_eq(¤t_etag)), } } mod files { use super::*; pub struct GetHandler { pub app: Arc>, } impl Handler for GetHandler { fn handle(&self, req: &mut Request) -> IronResult { let app = self.app.read().unwrap(); let capture = req.extensions.get::().unwrap().clone(); let old_etags = req.headers.get::(); match capture.find("id") { Some(id) => { let info = app.get_metadata(String::from(id)); match (info, old_etags) { (Ok(info_), Some(if_none_match)) => { if compare_etags(info_, if_none_match) { return Ok(Response::with(status::NotModified)); } } _ => (), } match app.get_file(String::from(id)) { Ok((info, stream)) => Ok(Response::with(( status::Ok, Header(headers::ContentType( info.file_type.parse::().unwrap(), )), Header(headers::ETag(headers::EntityTag::new(false, info.hash))), BodyReader(stream), ))), Err(_err) => Ok(Response::with(status::NotFound)), } } _ => Ok(Response::with(status::BadRequest)), } } } pub struct GetThumbnailHandler { pub app: Arc>, } impl Handler for GetThumbnailHandler { fn handle(&self, req: &mut Request) -> IronResult { let app = self.app.read().unwrap(); let capture = req.extensions.get::().unwrap().clone(); let old_etags = req.headers.get::(); match capture.find("id") { Some(id) => { let info = app.get_metadata(String::from(id)); match (info, old_etags) { (Ok(info_), Some(if_none_match)) => { if compare_etags(info_, if_none_match) { return Ok(Response::with(status::NotModified)); } } _ => (), } match app.get_thumbnail(id) { Ok((info, stream)) => Ok(Response::with(( status::Ok, Header(headers::ContentType( info.file_type.parse::().unwrap(), )), Header(headers::ETag(headers::EntityTag::new(false, info.hash))), BodyReader(stream), ))), Err(_err) => Ok(Response::with(status::NotFound)), } } _ => Ok(Response::with(status::BadRequest)), } } } pub struct PostHandler { pub app: Arc>, } impl Handler for PostHandler { fn handle(&self, req: &mut Request) -> IronResult { let mut app = self.app.write().unwrap(); let m_token = req.extensions.get::(); match m_token { Some(token) => { if token.check_authorizations(is_admin) { let params = req.get_ref::().unwrap(); if let Value::File(f_info) = params.get("file").unwrap() { match app.add_file( &f_info.path, &f_info.filename.clone().map(|fname| PathBuf::from(fname)), ) { Ok(_) => Ok(Response::with(( status::MovedPermanently, Redirect(router::url_for(req, "index", HashMap::new())), ))), Err(_) => Ok(Response::with(status::InternalServerError)), } } else { Ok(Response::with(status::BadRequest)) } } else { Ok(Response::with(status::Forbidden)) } } None => Ok(Response::with(status::Forbidden)), } } } pub struct DeleteHandler { pub app: Arc>, } impl Handler for DeleteHandler { fn handle(&self, req: &mut Request) -> IronResult { let mut app = self.app.write().unwrap(); let capture = req.extensions.get::().unwrap().clone(); let m_token = req.extensions.get::(); match m_token { Some(token) => { if token.check_authorizations(is_admin) { match capture.find("id") { Some(id) => match app.delete_file(String::from(id)) { Ok(()) => Ok(Response::with(( status::MovedPermanently, Redirect(router::url_for(req, "index", HashMap::new())), ))), Err(_) => Ok(Response::with(status::InternalServerError)), }, None => Ok(Response::with(status::BadRequest)), } } else { Ok(Response::with(status::Forbidden)) } } None => Ok(Response::with(status::Forbidden)), } } } } fn css(_: &mut Request) -> IronResult { let mut css: String = String::from(""); File::open("templates/style.css") .unwrap() .read_to_string(&mut css) .unwrap(); Ok(Response::with(( status::Ok, Header(headers::ContentType(iron::mime::Mime( iron::mime::TopLevel::Text, iron::mime::SubLevel::Css, vec![], ))), css, ))) } fn script(_: &mut Request) -> IronResult { let mut js: String = String::from(""); File::open("templates/script.js") .unwrap() .read_to_string(&mut js) .unwrap(); Ok(Response::with(( status::Ok, Header(headers::ContentType(iron::mime::Mime( iron::mime::TopLevel::Text, iron::mime::SubLevel::Javascript, vec![], ))), js, ))) } */ #[tokio::main] pub async fn main() { /* let auth_db_path = std::env::var("ORIZENTIC_DB").unwrap(); let secret = Secret(Vec::from( std::env::var("ORIZENTIC_SECRET").unwrap().as_bytes(), )); let auth_middleware = Authentication::new(secret, auth_db_path); let mut router = Router::new(); router.get( "/:id", files::GetFileHandler { app: app.clone(), template: compile_path("templates/file.html").expect("the template to compile"), }, "get-file-page", ); router.get( "/:id/raw", files::GetHandler { app: app.clone() }, "get-file", ); router.post("/", files::PostHandler { app: app.clone() }, "upload-file"); router.delete( "/:id", files::DeleteHandler { app: app.clone() }, "delete-file", ); router.get("/css", css, "styles"); router.get("/script", script, "script"); let mut chain = Chain::new(router); chain.link_before(auth_middleware); chain.link_before(RestForm {}); Iron::new(chain).http("0.0.0.0:3000").unwrap(); */ /* let root = warp::path!().and(warp::get()).map({ || { warp::http::Response::builder() .header("content-type", "text/html") .status(StatusCode::NOT_MODIFIED) .body(()) } }); let server = warp::serve(root); server .run(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 8002)) .await; */ let app = Arc::new(RwLock::new(App::new(Path::new( &std::env::var("FILE_SHARE_DIR").unwrap(), )))); let root = warp::path!().map({ let app = app.clone(); move || { warp::http::Response::builder() .header("content-type", "text/html") .status(StatusCode::OK) .body(pages::index(app.read().unwrap().list_files()).to_html_string()) } }); let thumbnail = warp::path!(String / "tn") .and(warp::header::optional::("if-none-match")) .map({ let app = app.clone(); move |id: String, old_etags: Option| { let mut content = Vec::new(); match app.read().unwrap().get_thumbnail(&id) { Ok((info, mut stream)) => match old_etags { Some(old_etags) if old_etags != info.hash => { warp::http::Response::builder() .header("content-type", info.file_type) .status(StatusCode::NOT_MODIFIED) .body(content) } _ => { let _ = stream.read_to_end(&mut content); warp::http::Response::builder() .header("content-type", info.file_type) .header("etag", info.hash) .status(StatusCode::OK) .body(content) } }, Err(_err) => warp::http::Response::builder() .status(StatusCode::NOT_FOUND) .body(content), } } }); let server = warp::serve(root.or(thumbnail)); server .run(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 8002)) .await; }