Set up the delete route

Sets up the delete route, including post-delete redirect back to the root.
Also adds logging.

Delete does not actually delete things yet.
This commit is contained in:
Savanni D'Gerinel 2023-09-22 00:38:26 -04:00
parent f440e6f7ad
commit 8c099d0586
5 changed files with 182 additions and 52 deletions

60
Cargo.lock generated
View File

@ -622,6 +622,19 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "env_logger"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0"
dependencies = [
"humantime",
"is-terminal",
"log 0.4.20",
"regex",
"termcolor",
]
[[package]]
name = "equivalent"
version = "1.0.1"
@ -706,12 +719,14 @@ dependencies = [
"http",
"image 0.23.14",
"iron",
"log 0.4.20",
"logger",
"mime 0.3.17",
"mime_guess 2.0.4",
"mustache",
"orizentic",
"params",
"pretty_env_logger",
"router",
"serde 1.0.188",
"serde_json",
@ -1532,6 +1547,12 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "hyper"
version = "0.10.16"
@ -1746,6 +1767,17 @@ dependencies = [
"url 1.7.2",
]
[[package]]
name = "is-terminal"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
dependencies = [
"hermit-abi 0.3.2",
"rustix",
"windows-sys",
]
[[package]]
name = "itertools"
version = "0.10.5"
@ -2634,6 +2666,16 @@ version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "pretty_env_logger"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c"
dependencies = [
"env_logger",
"log 0.4.20",
]
[[package]]
name = "proc-macro-crate"
version = "1.3.1"
@ -3421,6 +3463,15 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "termcolor"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64"
dependencies = [
"winapi-util",
]
[[package]]
name = "textwrap"
version = "0.11.0"
@ -4079,6 +4130,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"

View File

@ -27,3 +27,5 @@ thiserror = "1.0.20"
tokio = { version = "1", features = [ "full" ] }
uuid = { version = "0.4", features = [ "serde", "v4" ] }
warp = { version = "0.3" }
pretty_env_logger = { version = "0.5" }
log = { version = "0.4" }

View File

@ -2,6 +2,7 @@ use build_html::{self, Html, HtmlContainer};
#[derive(Clone, Debug)]
pub struct Form {
path: String,
method: String,
encoding: Option<String>,
elements: String,
@ -10,12 +11,18 @@ pub struct Form {
impl Form {
pub fn new() -> Self {
Self {
path: "/".to_owned(),
method: "get".to_owned(),
encoding: None,
elements: "".to_owned(),
}
}
pub fn with_path(mut self, path: &str) -> Self {
self.path = path.to_owned();
self
}
pub fn with_method(mut self, method: &str) -> Self {
self.method = method.to_owned();
self
@ -30,11 +37,12 @@ impl Form {
impl Html for Form {
fn to_html_string(&self) -> String {
let encoding = match self.encoding {
Some(ref encoding) => format!("encoding={encoding}", encoding = encoding),
Some(ref encoding) => format!("encoding=\"{encoding}\"", encoding = encoding),
None => format!(""),
};
format!(
"<form method={method} {encoding}>\n{elements}\n</form>\n",
"<form action=\"{path}\" method=\"{method}\" {encoding}>\n{elements}\n</form>\n",
path = self.path,
method = self.method,
encoding = encoding,
elements = self.elements.to_html_string()
@ -52,36 +60,58 @@ impl HtmlContainer for Form {
pub struct Input {
ty: String,
name: String,
id: String,
id: Option<String>,
value: Option<String>,
content: Option<String>,
}
impl Html for Input {
fn to_html_string(&self) -> String {
let id = match self.id {
Some(ref id) => format!("id=\"{}\"", id),
None => "".to_owned(),
};
let value = match self.value {
Some(ref value) => format!("value=\"{}\"", value),
None => "".to_owned(),
};
format!(
"<input type=\"{ty}\" name=\"{name}\" id=\"{id}\">{value}</input>\n",
"<input type=\"{ty}\" name=\"{name}\" {id} {value}>{content}</input>\n",
ty = self.ty,
name = self.name,
id = self.id,
value = self.value.clone().unwrap_or("".to_owned()),
id = id,
value = value,
content = self.content.clone().unwrap_or("".to_owned()),
)
}
}
impl Input {
pub fn new(ty: &str, name: &str, id: &str) -> Self {
pub fn new(ty: &str, name: &str) -> Self {
Self {
ty: ty.to_owned(),
name: name.to_owned(),
id: id.to_owned(),
id: None,
value: None,
content: None,
}
}
pub fn with_id(mut self, val: &str) -> Self {
self.id = Some(val.to_owned());
self
}
pub fn with_value(mut self, val: &str) -> Self {
self.value = Some(val.to_owned());
self
}
pub fn with_content(mut self, val: &str) -> Self {
self.content = Some(val.to_owned());
self
}
}
#[derive(Clone, Debug)]
@ -111,25 +141,29 @@ impl Html for Label {
#[derive(Clone, Debug)]
pub struct Button {
name: String,
text: String,
name: Option<String>,
label: String,
}
impl Button {
pub fn new(name: &str, text: &str) -> Self {
pub fn new(label: &str) -> Self {
Self {
name: name.to_owned(),
text: text.to_owned(),
name: None,
label: label.to_owned(),
}
}
}
impl Html for Button {
fn to_html_string(&self) -> String {
let name = match self.name {
Some(ref name) => format!("name={}", name),
None => "".to_owned(),
};
format!(
"<button name={name}>{text}</button>",
name = self.name,
text = self.text
"<button {name}>{label}</button>",
name = name,
label = self.label
)
}
}

View File

@ -6,11 +6,15 @@ use iron::prelude::*;
use iron::response::BodyReader;
use iron::status;
*/
#[macro_use]
extern crate log;
use http::status::StatusCode;
// use mustache::{compile_path, Template};
// use orizentic::{Permissions, ResourceName, Secret};
use build_html::Html;
use std::{
collections::HashMap,
io::Read,
net::{IpAddr, Ipv4Addr, SocketAddr},
path::Path,
@ -254,21 +258,6 @@ pub async fn main() {
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(
@ -301,13 +290,18 @@ pub async fn main() {
.await;
*/
pretty_env_logger::init();
let app = Arc::new(RwLock::new(App::new(Path::new(
&std::env::var("FILE_SHARE_DIR").unwrap(),
))));
let root = warp::path!().map({
let log = warp::log("file_service");
let root = warp::path!().and(warp::get()).map({
let app = app.clone();
move || {
info!("root handler");
warp::http::Response::builder()
.header("content-type", "text/html")
.status(StatusCode::OK)
@ -315,7 +309,20 @@ pub async fn main() {
}
});
let post_handler = warp::path!(String)
.and(warp::post())
.and(warp::filters::body::form())
.map(|id: String, form: HashMap<String, String>| {
info!("post_delete {}", id);
info!("form: {:?}", form);
warp::http::Response::builder()
.header("location", "/")
.status(StatusCode::SEE_OTHER)
.body(vec![])
});
let thumbnail = warp::path!(String / "tn")
.and(warp::get())
.and(warp::header::optional::<String>("if-none-match"))
.map({
let app = app.clone();
@ -332,6 +339,7 @@ pub async fn main() {
});
let file = warp::path!(String)
.and(warp::get())
.and(warp::header::optional::<String>("if-none-match"))
.map({
let app = app.clone();
@ -343,7 +351,24 @@ pub async fn main() {
}
});
let server = warp::serve(root.or(file).or(thumbnail));
let upload = warp::path!().and(warp::post()).map(|| {
println!("upload");
warp::reply()
});
let delete = warp::path!(String).and(warp::delete()).map(|id: String| {
println!("delete {}", id);
warp::reply()
});
let server = warp::serve(
root.or(post_handler)
.or(file)
.or(thumbnail)
.or(upload)
.or(delete)
.with(log),
);
server
.run(SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 8002))
.await;

View File

@ -11,30 +11,39 @@ pub fn index(files: Vec<Result<File, FileError>>) -> build_html::HtmlPage {
.with_encoding("multipart/form-data")
.with_container(
Container::new(ContainerType::Div)
.with_html(Input::new("file", "file", "file-selector-input"))
.with_html(Input::new("file", "file"))
.with_html(Label::new("for-selector-input", "Select a file")),
)
.with_html(Button::new("upload", "Upload file")),
.with_html(Button::new("Upload file")),
);
for file in files {
let mut container =
Container::new(ContainerType::Div).with_attributes(vec![("class", "file")]);
match file {
Ok(file) => {
let tn = Container::new(ContainerType::Div)
.with_attributes(vec![("class", "thumbnail")])
.with_link(
format!("/{}", file.info().id),
Image::new(&format!("{}/tn", file.info().id)).to_html_string(),
);
container.add_html(tn);
}
Err(err) => {
container.add_paragraph(format!("{:?}", err));
}
}
page.add_container(container);
let container = match file {
Ok(ref file) => thumbnail(file).with_html(
Form::new()
.with_path(&format!("/{}", file.info().id))
.with_method("post")
.with_html(Input::new("hidden", "_method").with_value("delete"))
.with_html(Button::new("Delete")),
),
Err(err) => Container::new(ContainerType::Div)
.with_attributes(vec![("class", "file")])
.with_paragraph(format!("{:?}", err)),
};
page.add_container(container)
}
page
}
pub fn thumbnail(file: &File) -> Container {
let mut container = Container::new(ContainerType::Div).with_attributes(vec![("class", "file")]);
let tn = Container::new(ContainerType::Div)
.with_attributes(vec![("class", "thumbnail")])
.with_link(
format!("/{}", file.info().id),
Image::new(&format!("{}/tn", file.info().id)).to_html_string(),
);
container.add_html(tn);
container
}