From 5b338c40daa2191e68722ba2fd1686c7c76b9984 Mon Sep 17 00:00:00 2001 From: sigoden Date: Tue, 27 Aug 2024 16:07:17 +0800 Subject: [PATCH] refactor: make logout works on safari (#442) --- assets/index.js | 16 ++++++++++------ src/auth.rs | 3 ++- src/server.rs | 16 ++++++++++++---- tests/auth.rs | 26 +++++++++++++++++++------- tests/http.rs | 2 +- 5 files changed, 44 insertions(+), 19 deletions(-) diff --git a/assets/index.js b/assets/index.js index 5141649..2b51d2a 100644 --- a/assets/index.js +++ b/assets/index.js @@ -91,6 +91,10 @@ let $emptyFolder; * @type Element */ let $editor; +/** + * @type Element + */ +let $loginBtn; /** * @type Element */ @@ -121,6 +125,7 @@ async function ready() { $uploadersTable = document.querySelector(".uploaders-table"); $emptyFolder = document.querySelector(".empty-folder"); $editor = document.querySelector(".editor"); + $loginBtn = document.querySelector(".login-btn"); $logoutBtn = document.querySelector(".logout-btn"); $userName = document.querySelector(".user-name"); @@ -517,13 +522,12 @@ async function setupAuth() { $logoutBtn.addEventListener("click", logout); $userName.textContent = DATA.user; } else { - const $loginBtn = document.querySelector(".login-btn"); $loginBtn.classList.remove("hidden"); $loginBtn.addEventListener("click", async () => { try { await checkAuth(); - location.reload(); } catch {} + location.reload(); }); } } @@ -745,19 +749,19 @@ async function saveChange() { async function checkAuth() { if (!DATA.auth) return; const res = await fetch(baseUrl(), { - method: "AUTH", + method: "CHECKAUTH", }); await assertResOK(res); - document.querySelector(".login-btn").classList.add("hidden"); + $loginBtn.classList.add("hidden"); $logoutBtn.classList.remove("hidden"); - $userName.textContent = ""; + $userName.textContent = await res.text(); } function logout() { if (!DATA.auth) return; const url = baseUrl(); const xhr = new XMLHttpRequest(); - xhr.open("AUTH", url, true, ":"); + xhr.open("LOGOUT", url, true, DATA.user); xhr.onload = () => { location.href = url; } diff --git a/src/auth.rs b/src/auth.rs index 6a58fa9..878dc30 100644 --- a/src/auth.rs +++ b/src/auth.rs @@ -429,7 +429,8 @@ fn is_readonly_method(method: &Method) -> bool { || method == Method::OPTIONS || method == Method::HEAD || method.as_str() == "PROPFIND" - || method.as_str() == "AUTH" + || method.as_str() == "CHECKAUTH" + || method.as_str() == "LOGOUT" } fn strip_prefix<'a>(search: &'a [u8], prefix: &[u8]) -> Option<&'a [u8]> { diff --git a/src/server.rs b/src/server.rs index d623ad3..2343fe5 100644 --- a/src/server.rs +++ b/src/server.rs @@ -200,11 +200,17 @@ impl Server { .map(|(k, v)| (k.to_string(), v.to_string())) .collect(); - if method.as_str() == "AUTH" { - if user.is_none() { - self.auth_reject(&mut res)?; + if method.as_str() == "CHECKAUTH" { + match user.clone() { + Some(user) => { + *res.body_mut() = body_full(user); + } + None => self.auth_reject(&mut res)?, } return Ok(res); + } else if method.as_str() == "LOGOUT" { + self.auth_reject(&mut res)?; + return Ok(res); } let head_only = method == Method::HEAD; @@ -1722,7 +1728,9 @@ fn is_hidden(hidden: &[String], file_name: &str, is_dir_type: bool) -> bool { fn set_webdav_headers(res: &mut Response) { res.headers_mut().insert( "Allow", - HeaderValue::from_static("GET,HEAD,PUT,OPTIONS,DELETE,PATCH,PROPFIND,COPY,MOVE"), + HeaderValue::from_static( + "GET,HEAD,PUT,OPTIONS,DELETE,PATCH,PROPFIND,COPY,MOVE,CHECKAUTH,LOGOUT", + ), ); res.headers_mut() .insert("DAV", HeaderValue::from_static("1, 2, 3")); diff --git a/tests/auth.rs b/tests/auth.rs index 04a3782..535ecb5 100644 --- a/tests/auth.rs +++ b/tests/auth.rs @@ -119,29 +119,41 @@ fn auth_check( #[with(&["--auth", "user:pass@/:rw", "--auth", "user2:pass2@/", "-A"])] server: TestServer, ) -> Result<(), Error> { let url = format!("{}index.html", server.url()); - let resp = fetch!(b"AUTH", &url).send()?; + let resp = fetch!(b"CHECKAUTH", &url).send()?; assert_eq!(resp.status(), 401); - let resp = send_with_digest_auth(fetch!(b"AUTH", &url), "user", "pass")?; + let resp = send_with_digest_auth(fetch!(b"CHECKAUTH", &url), "user", "pass")?; assert_eq!(resp.status(), 200); - let resp = send_with_digest_auth(fetch!(b"AUTH", &url), "user2", "pass2")?; + let resp = send_with_digest_auth(fetch!(b"CHECKAUTH", &url), "user2", "pass2")?; assert_eq!(resp.status(), 200); Ok(()) } #[rstest] -fn auth_compact_rules( +fn auth_check2( #[with(&["--auth", "user:pass@/:rw|user2:pass2@/", "-A"])] server: TestServer, ) -> Result<(), Error> { let url = format!("{}index.html", server.url()); - let resp = fetch!(b"AUTH", &url).send()?; + let resp = fetch!(b"CHECKAUTH", &url).send()?; assert_eq!(resp.status(), 401); - let resp = send_with_digest_auth(fetch!(b"AUTH", &url), "user", "pass")?; + let resp = send_with_digest_auth(fetch!(b"CHECKAUTH", &url), "user", "pass")?; assert_eq!(resp.status(), 200); - let resp = send_with_digest_auth(fetch!(b"AUTH", &url), "user2", "pass2")?; + let resp = send_with_digest_auth(fetch!(b"CHECKAUTH", &url), "user2", "pass2")?; assert_eq!(resp.status(), 200); Ok(()) } +#[rstest] +fn auth_logout( + #[with(&["--auth", "user:pass@/:rw", "-A"])] server: TestServer, +) -> Result<(), Error> { + let url = format!("{}index.html", server.url()); + let resp = fetch!(b"LOGOUT", &url).send()?; + assert_eq!(resp.status(), 401); + let resp = send_with_digest_auth(fetch!(b"LOGOUT", &url), "user", "pass")?; + assert_eq!(resp.status(), 401); + Ok(()) +} + #[rstest] fn auth_readonly( #[with(&["--auth", "user:pass@/:rw", "--auth", "user2:pass2@/", "-A"])] server: TestServer, diff --git a/tests/http.rs b/tests/http.rs index 96f790d..28c9d79 100644 --- a/tests/http.rs +++ b/tests/http.rs @@ -265,7 +265,7 @@ fn options_dir(server: TestServer) -> Result<(), Error> { assert_eq!(resp.status(), 200); assert_eq!( resp.headers().get("allow").unwrap(), - "GET,HEAD,PUT,OPTIONS,DELETE,PATCH,PROPFIND,COPY,MOVE" + "GET,HEAD,PUT,OPTIONS,DELETE,PATCH,PROPFIND,COPY,MOVE,CHECKAUTH,LOGOUT" ); assert_eq!(resp.headers().get("dav").unwrap(), "1, 2, 3"); Ok(())