1#![warn(clippy::all, clippy::pedantic, clippy::nursery)]
2#![allow(clippy::missing_errors_doc, clippy::missing_panics_doc)]
3use axum::{Extension, Router};
4use derive_more::Constructor;
5use principal::PrincipalResourceService;
6use rustical_dav::resource::{PrincipalUri, ResourceService};
7use rustical_dav::resources::RootResourceService;
8use rustical_store::auth::middleware::AuthenticationLayer;
9use rustical_store::auth::{AuthenticationProvider, Principal};
10use rustical_store::{CalendarStore, SubscriptionStore};
11use serde::{Deserialize, Serialize};
12use std::sync::Arc;
13
14pub mod calendar;
15pub mod calendar_object;
16pub mod error;
17pub mod principal;
18pub use error::Error;
19
20#[derive(Debug, Clone, Constructor)]
21pub struct CalDavPrincipalUri(&'static str);
22
23impl PrincipalUri for CalDavPrincipalUri {
24 fn principal_collection(&self) -> String {
25 format!("{}/principal/", self.0)
26 }
27 fn principal_uri(&self, principal: &str) -> String {
28 format!("{}{}/", self.principal_collection(), principal)
29 }
30}
31
32pub fn caldav_router<AP: AuthenticationProvider, C: CalendarStore, S: SubscriptionStore>(
33 prefix: &'static str,
34 auth_provider: Arc<AP>,
35 store: Arc<C>,
36 subscription_store: Arc<S>,
37 simplified_home_set: bool,
38 config: Arc<CalDavConfig>,
39) -> Router {
40 Router::new().nest(
41 prefix,
42 RootResourceService::<_, Principal, CalDavPrincipalUri>::new(PrincipalResourceService {
43 auth_provider: auth_provider.clone(),
44 sub_store: subscription_store,
45 cal_store: store,
46 simplified_home_set,
47 config,
48 })
49 .axum_router()
50 .layer(AuthenticationLayer::new(auth_provider))
51 .layer(Extension(CalDavPrincipalUri(prefix))),
52 )
53}
54
55const fn default_true() -> bool {
56 true
57}
58
59#[derive(Debug, Clone, Deserialize, Serialize)]
60#[serde(deny_unknown_fields, default)]
61pub struct CalDavConfig {
62 #[serde(default = "default_true")]
63 rfc7809: bool,
64}
65
66impl Default for CalDavConfig {
67 fn default() -> Self {
68 Self { rfc7809: true }
69 }
70}