Compare commits

..

No commits in common. "1bb6bd78e6943989291d02d13590cf1ecb2696bc" and "56d7fae43ce96cb3e68d924daad2370b9e5bec83" have entirely different histories.

3 changed files with 83 additions and 54 deletions

View File

@ -133,22 +133,3 @@ impl Html for Button {
) )
} }
} }
#[derive(Clone, Debug)]
pub struct Image {
path: String,
}
impl Image {
pub fn new(path: &str) -> Self {
Self {
path: path.to_owned(),
}
}
}
impl Html for Image {
fn to_html_string(&self) -> String {
format!("<img src={path} />", path = self.path,)
}
}

View File

@ -11,7 +11,6 @@ use http::status::StatusCode;
// use orizentic::{Permissions, ResourceName, Secret}; // use orizentic::{Permissions, ResourceName, Secret};
use build_html::Html; use build_html::Html;
use std::{ use std::{
io::Read,
net::{IpAddr, Ipv4Addr, SocketAddr}, net::{IpAddr, Ipv4Addr, SocketAddr},
path::Path, path::Path,
sync::{Arc, RwLock}, sync::{Arc, RwLock},
@ -46,6 +45,71 @@ pub fn compare_etags(info: FileInfo, etag_list: &headers::IfNoneMatch) -> bool {
mod files { mod files {
use super::*; use super::*;
pub struct IndexHandler {
pub app: Arc<RwLock<App>>,
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<TemplateFile>,
}
impl Handler for IndexHandler {
fn handle(&self, req: &mut Request) -> IronResult<Response> {
let app = self.app.read().unwrap();
let m_token = req.extensions.get::<Authentication>();
match m_token {
Some(token) => {
if token.check_authorizations(is_admin) {
let files: Vec<TemplateFile> = 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 struct GetHandler {
pub app: Arc<RwLock<App>>, pub app: Arc<RwLock<App>>,
} }
@ -231,6 +295,14 @@ pub async fn main() {
let auth_middleware = Authentication::new(secret, auth_db_path); let auth_middleware = Authentication::new(secret, auth_db_path);
let mut router = Router::new(); 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( router.get(
"/:id", "/:id",
@ -247,6 +319,12 @@ pub async fn main() {
"get-file", "get-file",
); );
router.get(
"/:id/tn",
files::GetThumbnailHandler { app: app.clone() },
"get-thumbnail",
);
router.post("/", files::PostHandler { app: app.clone() }, "upload-file"); router.post("/", files::PostHandler { app: app.clone() }, "upload-file");
router.delete( router.delete(
@ -293,37 +371,7 @@ pub async fn main() {
} }
}); });
let thumbnail = warp::path!(String / "tn") let server = warp::serve(root);
.and(warp::header::optional::<String>("if-none-match"))
.map({
let app = app.clone();
move |id: String, old_etags: Option<String>| {
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 server
.run(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 8002)) .run(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 8002))
.await; .await;

View File

@ -1,5 +1,5 @@
use crate::{html::*, File, FileError}; use crate::{html::*, File, FileError};
use build_html::{self, Container, ContainerType, Html, HtmlContainer}; use build_html::{self, Container, ContainerType, HtmlContainer};
pub fn index(files: Vec<Result<File, FileError>>) -> build_html::HtmlPage { pub fn index(files: Vec<Result<File, FileError>>) -> build_html::HtmlPage {
let mut page = build_html::HtmlPage::new() let mut page = build_html::HtmlPage::new()
@ -25,8 +25,8 @@ pub fn index(files: Vec<Result<File, FileError>>) -> build_html::HtmlPage {
let tn = Container::new(ContainerType::Div) let tn = Container::new(ContainerType::Div)
.with_attributes(vec![("class", "thumbnail")]) .with_attributes(vec![("class", "thumbnail")])
.with_link( .with_link(
format!("/{}", file.info().id), format!("/file/{}", file.info().id),
Image::new(&format!("{}/tn", file.info().id)).to_html_string(), "<p> paragraph within the link </p>".to_owned(),
); );
container.add_html(tn); container.add_html(tn);
} }