webdav token regeneration

This commit is contained in:
2025-10-31 20:37:07 +01:00
parent e9731ec691
commit 18352caabe
14 changed files with 304 additions and 69 deletions
+1 -2
View File
@@ -37,8 +37,7 @@ use tower::util::ServiceExt;
use uuid::Uuid;
const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations");
const RESET_DATABASE_SQL: &str =
"DROP SCHEMA IF EXISTS tenant CASCADE;\n\
const RESET_DATABASE_SQL: &str = "DROP SCHEMA IF EXISTS tenant CASCADE;\n\
DROP SCHEMA IF EXISTS shared CASCADE;\n\
DROP SCHEMA IF EXISTS public CASCADE;\n\
CREATE SCHEMA public;\n\
+68 -2
View File
@@ -54,6 +54,20 @@ async fn webdav_token_api_crud() -> Result<()> {
assert_eq!(created.info.label.as_deref(), Some("dav"));
assert!(created.info.last_used_at.is_none());
let regenerate_response = app
.post_json(
&format!("/api/profile/webdav-tokens/{token_id}/regenerate"),
&json!({}),
Some(&access_token),
)
.await?;
assert_eq!(regenerate_response.status(), StatusCode::OK);
let regenerate_body = body_to_vec(regenerate_response.into_body()).await?;
let regenerated: CreateTokenResponse = serde_json::from_slice(&regenerate_body)?;
assert_eq!(regenerated.info.id, token_id);
assert_ne!(regenerated.token, created.token);
assert!(regenerated.info.last_used_at.is_none());
let list_response = app
.get("/api/profile/webdav-tokens", Some(&access_token))
.await?;
@@ -106,9 +120,10 @@ async fn webdav_basic_auth_uses_tokens() -> Result<()> {
let token_id = created.info.id;
let router = webdav::create_router().with_state(app.state.clone());
let original_secret = created.token.clone();
let auth_header = format!(
"Basic {}",
BASE64.encode(format!("{}:{}", username, created.token))
BASE64.encode(format!("{}:{}", username, original_secret))
);
let propfind = Method::from_bytes(b"PROPFIND")?;
@@ -131,6 +146,57 @@ async fn webdav_basic_auth_uses_tokens() -> Result<()> {
.await?;
assert!(used.is_some());
let regenerate_response = app
.post_json(
&format!("/api/profile/webdav-tokens/{token_id}/regenerate"),
&json!({}),
Some(&access_token),
)
.await?;
assert_eq!(regenerate_response.status(), StatusCode::OK);
let regenerate_body = body_to_vec(regenerate_response.into_body()).await?;
let regenerated: CreateTokenResponse = serde_json::from_slice(&regenerate_body)?;
assert_ne!(regenerated.token, original_secret);
let unused_after_regen = app
.with_conn(move |conn| {
let record = webdav_tokens::table
.find(token_id)
.first::<WebdavToken>(conn)?;
Ok::<_, anyhow::Error>(record.last_used_at)
})
.await?;
assert!(unused_after_regen.is_none());
let old_secret_request = Request::builder()
.method(propfind.clone())
.uri("/")
.header(
header::AUTHORIZATION,
format!(
"Basic {}",
BASE64.encode(format!("{}:{}", username, original_secret))
),
)
.header("depth", "0")
.body(Body::empty())?;
let old_secret_response = router.clone().oneshot(old_secret_request).await?;
assert_eq!(old_secret_response.status(), StatusCode::UNAUTHORIZED);
let new_secret_header = format!(
"Basic {}",
BASE64.encode(format!("{}:{}", username, regenerated.token))
);
let success_request = Request::builder()
.method(propfind.clone())
.uri("/")
.header(header::AUTHORIZATION, new_secret_header.clone())
.header("depth", "0")
.body(Body::empty())?;
let response = router.clone().oneshot(success_request).await?;
assert_eq!(response.status(), StatusCode::MULTI_STATUS);
let delete_response = app
.delete(
&format!("/api/profile/webdav-tokens/{token_id}"),
@@ -142,7 +208,7 @@ async fn webdav_basic_auth_uses_tokens() -> Result<()> {
let failure_request = Request::builder()
.method(propfind)
.uri("/")
.header(header::AUTHORIZATION, auth_header)
.header(header::AUTHORIZATION, new_secret_header)
.header("depth", "0")
.body(Body::empty())?;
let response = router.oneshot(failure_request).await?;