diff --git a/src/args.rs b/src/args.rs
index 4fdeba8..2448ae6 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -34,6 +34,7 @@ fn app() -> clap::Command<'static> {
.long("readonly")
.help("Only serve static files, no operations like upload and delete");
+
let arg_auth = Arg::new("auth")
.short('a')
.long("auth")
diff --git a/src/index.css b/src/index.css
index f59b195..76acb01 100644
--- a/src/index.css
+++ b/src/index.css
@@ -59,14 +59,26 @@ html {
}
.main .cell-name {
- max-width: 300px;
+ width: 300px;
+}
+
+.main .cell-mtime {
+ width: 150px;
+ padding-left: 1em;
}
.main .cell-size {
text-align: right;
- width: 80px;
+ width: 100px;
+ padding-left: 1em;
+}
+
+.main .cell-actions {
+ width: 100px;
+ padding-left: 1em;
}
+
.path svg {
height: 100%;
fill: rgba(3,47,98,0.5);
@@ -98,5 +110,5 @@ html {
}
.uploader {
- padding-right: 2em;
-}
\ No newline at end of file
+ padding-right: 1em;
+}
diff --git a/src/index.html b/src/index.html
index 3174871..d77b8a0 100644
--- a/src/index.html
+++ b/src/index.html
@@ -103,17 +103,41 @@
}
}
- function addFile(file) {
+ function addPath(file, index) {
+ const actionTd = file.name === ".." || readonly ? "" : `
+
+
+ | `
+
$tbody.insertAdjacentHTML("beforeend", `
-
+
${getSvg(file.path_type)}
${file.name}
|
${formatMtime(file.mtime)} |
${formatSize(file.size)} |
-
-`)
+ ${actionTd}
+ `)
+ }
+
+ async function deletePath(index) {
+ const file = paths[index];
+ if (!file) return;
+ try {
+ const res = await fetch(encodeURI(file.path), {
+ method: "DELETE",
+ });
+ if (res.status !== 200) {
+ const text = await res.text();
+ throw new Error(text);
+ }
+ document.getElementById(`addPath${index}`).remove();
+ } catch (err) {
+ alert(`Failed to delete ${file.name}, ${err.message}`);
+ }
}
function addUploadControl() {
@@ -164,11 +188,13 @@
}
+
document.addEventListener('DOMContentLoaded', () => {
addBreadcrumb(breadcrumb);
- paths.forEach(file => addFile(file));
- if (readonly) {
+ paths.forEach((file, index) => addPath(file, index));
+ if (!readonly) {
addUploadControl();
+ document.querySelector(".main thead tr").insertAdjacentHTML("beforeend", `Actions | `);
document.getElementById("file").addEventListener("change", e => {
const files = e.target.files;
for (const file of files) {
diff --git a/src/server.rs b/src/server.rs
index 663a77e..45ac63a 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -60,6 +60,12 @@ impl InnerService {
}
pub async fn handle(self: Arc, req: Request) -> Result {
+ if !self.auth_guard(&req).unwrap_or_default() {
+ let mut res = status_code!(StatusCode::UNAUTHORIZED);
+ res.headers_mut().insert("WWW-Authenticate" , HeaderValue::from_static("Basic"));
+ return Ok(res)
+ }
+
let res = if req.method() == Method::GET {
self.handle_static(req).await
} else if req.method() == Method::PUT {
@@ -67,6 +73,8 @@ impl InnerService {
return Ok(status_code!(StatusCode::FORBIDDEN));
}
self.handle_upload(req).await
+ } else if req.method() == Method::DELETE {
+ self.handle_delete(req).await
} else {
return Ok(status_code!(StatusCode::NOT_FOUND));
};
@@ -74,11 +82,6 @@ impl InnerService {
}
async fn handle_static(&self, req: Request) -> BoxResult {
- if !self.auth_guard(&req).unwrap_or_default() {
- let mut res = status_code!(StatusCode::UNAUTHORIZED);
- res.headers_mut().insert("WWW-Authenticate" , HeaderValue::from_static("Basic"));
- return Ok(res)
- }
let path = match self.get_file_path(req.uri().path())? {
Some(path) => path,
None => return Ok(status_code!(StatusCode::FORBIDDEN)),
@@ -96,11 +99,6 @@ impl InnerService {
}
async fn handle_upload(&self, mut req: Request) -> BoxResult {
- if !self.auth_guard(&req).unwrap_or_default() {
- let mut res = status_code!(StatusCode::UNAUTHORIZED);
- res.headers_mut().insert("WWW-Authenticate" , HeaderValue::from_static("Basic"));
- return Ok(res)
- }
let path = match self.get_file_path(req.uri().path())? {
Some(path) => path,
None => return Ok(status_code!(StatusCode::FORBIDDEN)),
@@ -125,6 +123,22 @@ impl InnerService {
return Ok(status_code!(StatusCode::OK));
}
+ async fn handle_delete(&self, req: Request) -> BoxResult {
+ let path = match self.get_file_path(req.uri().path())? {
+ Some(path) => path,
+ None => return Ok(status_code!(StatusCode::FORBIDDEN)),
+ };
+
+ let meta = fs::metadata(&path).await?;
+ if meta.is_file() {
+ fs::remove_file(path).await?;
+ } else {
+ fs::remove_dir_all(path).await?;
+ }
+ Ok(status_code!(StatusCode::OK))
+
+ }
+
async fn handle_send_dir(&self, path: &Path) -> BoxResult {
let base_path = &self.args.path;
let mut rd = fs::read_dir(path).await?;
@@ -179,7 +193,7 @@ impl InnerService {
paths.sort_unstable();
let breadcrumb = self.get_breadcrumb(path);
- let data = SendDirData { breadcrumb, paths, readonly: !self.args.readonly };
+ let data = SendDirData { breadcrumb, paths, readonly: self.args.readonly };
let data = serde_json::to_string(&data).unwrap();
let mut output =