use super::methods::{get_object, put_object}; use crate::{CardDavPrincipalUri, Error, address_object::resource::AddressObjectResource}; use async_trait::async_trait; use axum::{extract::Request, handler::Handler, response::Response}; use derive_more::derive::Constructor; use futures_util::future::BoxFuture; use rustical_dav::resource::{AxumMethods, ResourceService}; use rustical_store::{AddressbookStore, auth::Principal}; use serde::{Deserialize, Deserializer}; use std::{convert::Infallible, sync::Arc}; use tower::Service; #[derive(Constructor)] pub struct AddressObjectResourceService { pub(crate) addr_store: Arc, } impl Clone for AddressObjectResourceService { fn clone(&self) -> Self { Self { addr_store: self.addr_store.clone(), } } } #[derive(Debug, Clone, Deserialize)] pub struct AddressObjectPathComponents { pub principal: String, pub addressbook_id: String, #[serde(deserialize_with = "deserialize_vcf_name")] pub object_id: String, } #[async_trait] impl ResourceService for AddressObjectResourceService { type PathComponents = AddressObjectPathComponents; type Resource = AddressObjectResource; type MemberType = AddressObjectResource; type Error = Error; type Principal = Principal; type PrincipalUri = CardDavPrincipalUri; const DAV_HEADER: &str = "1, 3, access-control, addressbook"; async fn get_resource( &self, AddressObjectPathComponents { principal, addressbook_id, object_id, }: &Self::PathComponents, show_deleted: bool, ) -> Result { let object = self .addr_store .get_object(principal, addressbook_id, object_id, show_deleted) .await?; Ok(AddressObjectResource { object, principal: principal.to_owned(), }) } async fn delete_resource( &self, AddressObjectPathComponents { principal, addressbook_id, object_id, }: &Self::PathComponents, use_trashbin: bool, ) -> Result<(), Self::Error> { self.addr_store .delete_object(principal, addressbook_id, object_id, use_trashbin) .await?; Ok(()) } } impl AxumMethods for AddressObjectResourceService { fn get() -> Option BoxFuture<'static, Result>> { Some(|state, req| { let mut service = Handler::with_state(get_object::, state); Box::pin(Service::call(&mut service, req)) }) } fn put() -> Option BoxFuture<'static, Result>> { Some(|state, req| { let mut service = Handler::with_state(put_object::, state); Box::pin(Service::call(&mut service, req)) }) } } fn deserialize_vcf_name<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { let name: String = Deserialize::deserialize(deserializer)?; if let Some(object_id) = name.strip_suffix(".vcf") { Ok(object_id.to_owned()) } else { Err(serde::de::Error::custom("Missing .vcf extension")) } }