/* 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::{ 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 IndexHandler { pub app: Arc>, pub template: Template, } #[derive(Serialize)] pub enum TemplateFile { #[serde(rename = "error")] Error { error: String }, #[serde(rename = "file")] File { id: String, size: u64, date: String, type_: String, }, } #[derive(Serialize)] pub struct IndexTemplateParams { files: Vec, } impl Handler for IndexHandler { fn handle(&self, req: &mut Request) -> IronResult { let app = self.app.read().unwrap(); let m_token = req.extensions.get::(); match m_token { Some(token) => { if token.check_authorizations(is_admin) { let files: Vec = app .list_files() .into_iter() .map(|entry| match entry { Ok(file) => TemplateFile::File { id: file.info().id, size: file.info().size, date: format!( "{}", file.info().created.format("%Y-%m-%d %H:%M:%S") ), type_: file.info().file_type, }, Err(err) => TemplateFile::Error { error: format!("{}", err), }, }) .collect(); Ok(Response::with(( status::Ok, Header(headers::ContentType::html()), Header(headers::SetCookie(vec![format!("auth={}", token.text)])), self.template .render_to_string(&IndexTemplateParams { files }) .expect("the template to render"), ))) } else { Ok(Response::with(status::Forbidden)) } } None => Ok(Response::with(status::Forbidden)), } } } 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( "/", files::IndexHandler { app: app.clone(), template: compile_path("templates/index.html").expect("the template to compile"), }, "index", ); 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.get( "/:id/tn", files::GetThumbnailHandler { app: app.clone() }, "get-thumbnail", ); 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 server = warp::serve(root); server .run(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 8002)) .await; }