use super::super::app_state::AppState;
use crate::shared::{webdav::EntryPathPub, HttpResult};
use axum::{
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
};
pub async fn delete_entry(
State(state): State<AppState>,
Path(entry_path): Path<EntryPathPub>,
) -> HttpResult<impl IntoResponse> {
state.file_service.delete(entry_path.inner()).await?;
Ok(StatusCode::NO_CONTENT)
}
#[cfg(test)]
mod tests {
use super::super::super::app_state::AppState;
use super::*;
use crate::persistence::files::{FileIoError, FileService};
use crate::shared::webdav::{EntryPath, WebDavPath};
use crate::AppContext;
use axum::{routing::delete, Router};
use opendal::Buffer;
use pkarr::Keypair;
async fn write_test_file(file_service: &FileService, entry_path: &EntryPath) {
let buffer = Buffer::from(vec![0; 10]);
let _entry = file_service.write(entry_path, buffer).await.unwrap();
}
#[tokio::test]
async fn test_delete_entry() {
let context = AppContext::test();
let keypair = Keypair::from_secret_key(&[0; 32]);
let pubkey = keypair.public_key();
let file_path = "my_file.txt";
let db = context.db.clone();
let file_service = FileService::new_from_context(&context).unwrap();
let app_state = AppState::new(db.clone(), file_service.clone(), "");
let router = Router::new()
.route("/webdav/{*entry_path}", delete(delete_entry))
.with_state(app_state);
let webdav_path = WebDavPath::new(format!("/pub/{}", file_path).as_str()).unwrap();
db.create_user(&pubkey).unwrap();
let entry_path = EntryPath::new(pubkey.clone(), webdav_path);
write_test_file(&file_service, &entry_path).await;
let server = axum_test::TestServer::new(router).unwrap();
let response = server
.delete(format!("/webdav/{}{}", pubkey, entry_path.path().as_str()).as_str())
.await;
assert_eq!(response.status_code(), StatusCode::NO_CONTENT);
match db.get_entry(&entry_path) {
Ok(entry) => {
panic!("Entry should be deleted: {:?}", entry);
}
Err(FileIoError::NotFound) => {
}
Err(e) => {
panic!("Error getting entry: {}", e);
}
}
let events = db.list_events(None, None).unwrap();
assert_eq!(
events.len(),
3,
"One PUT and one DEL event should be created. Last entry is the cursor."
);
assert!(events[0].contains("PUT"));
assert!(events[1].contains("DEL"));
}
#[tokio::test]
async fn test_file_not_found() {
let context = AppContext::test();
let keypair = Keypair::from_secret_key(&[0; 32]);
let pubkey = keypair.public_key();
let file_path = "my_file.txt";
let db = context.db.clone();
let app_state = AppState::new(
db.clone(),
FileService::new_from_context(&context).unwrap(),
"",
);
let router = Router::new()
.route("/webdav/{*entry_path}", delete(delete_entry))
.with_state(app_state);
let url = format!("/webdav/{}/pub/{}", pubkey, file_path);
let server = axum_test::TestServer::new(router).unwrap();
let response = server.delete(url.as_str()).await;
assert_eq!(response.status_code(), StatusCode::NOT_FOUND);
}
#[tokio::test]
async fn test_invalid_pubkey() {
let context = AppContext::test();
let db = context.db.clone();
let app_state = AppState::new(
db.clone(),
FileService::new_from_context(&context).unwrap(),
"",
);
let router = Router::new()
.route("/webdav/{*entry_path}", delete(delete_entry))
.with_state(app_state);
let server = axum_test::TestServer::new(router).unwrap();
let response = server
.delete("/webdav/1234/pub/test.txt".to_string().as_str())
.await;
assert_eq!(response.status_code(), StatusCode::BAD_REQUEST);
}
}